blob: 9602a789906cceae509a8b67f3f54d46ee47bf7d [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
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000728// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
729// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
730// unsigned values.
731//
732// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
733// limited to only a few forms of the instruction.
734bool
735EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
736{
737#if 0
738 if ConditionPassed() then
739 EncodingSpecificOperations();
740 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
741 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
742 result = operand1 * operand2;
743 R[d] = result<31:0>;
744 if setflags then
745 APSR.N = result<31>;
746 APSR.Z = IsZeroBit(result);
747 if ArchVersion() == 4 then
748 APSR.C = bit UNKNOWN;
749 // else APSR.C unchanged
750 // APSR.V always unchanged
751#endif
752
753 bool success = false;
754 const uint32_t opcode = OpcodeAsUnsigned (&success);
755 if (!success)
756 return false;
757
758 if (ConditionPassed())
759 {
760 uint32_t d;
761 uint32_t n;
762 uint32_t m;
763 bool setflags;
764
765 // EncodingSpecificOperations();
766 switch (encoding)
767 {
768 case eEncodingT1:
769 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
770 d = Bits32 (opcode, 2, 0);
771 n = Bits32 (opcode, 5, 3);
772 m = Bits32 (opcode, 2, 0);
773 setflags = !InITBlock();
774
775 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
776 if ((ArchVersion() < ARMv6) && (d == n))
777 return false;
778
779 break;
780
781 case eEncodingT2:
782 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
783 d = Bits32 (opcode, 11, 8);
784 n = Bits32 (opcode, 19, 16);
785 m = Bits32 (opcode, 3, 0);
786 setflags = false;
787
788 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
789 if (BadReg (d) || BadReg (n) || BadReg (m))
790 return false;
791
792 break;
793
794 case eEncodingA1:
795 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
796 d = Bits32 (opcode, 19, 16);
797 n = Bits32 (opcode, 3, 0);
798 m = Bits32 (opcode, 11, 8);
799 setflags = BitIsSet (opcode, 20);
800
801 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
802 if ((d == 15) || (n == 15) || (m == 15))
803 return false;
804
805 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
806 if ((ArchVersion() < ARMv6) && (d == n))
807 return false;
808
809 break;
810
811 default:
812 return false;
813 }
814
815 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
816 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
817 if (!success)
818 return false;
819
820 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
821 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
822 if (!success)
823 return false;
824
825 // result = operand1 * operand2;
826 uint64_t result = operand1 * operand2;
827
828 // R[d] = result<31:0>;
829 Register op1_reg;
830 Register op2_reg;
831 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
832 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
833
834 EmulateInstruction::Context context;
835 context.type = eContextMultiplication;
836 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
837
838 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
839 return false;
840
841 // if setflags then
842 if (setflags)
843 {
844 // APSR.N = result<31>;
845 // APSR.Z = IsZeroBit(result);
846 m_new_inst_cpsr = m_inst_cpsr;
847 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
848 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
849 if (m_new_inst_cpsr != m_inst_cpsr)
850 {
851 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
852 return false;
853 }
854
855 // if ArchVersion() == 4 then
856 // APSR.C = bit UNKNOWN;
857 }
858 }
859 return true;
860}
861
Johnny Chend642a6a2011-02-22 01:01:03 +0000862// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
863// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000864bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000865EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000866{
867#if 0
868 // ARM pseudo code...
869 if (ConditionPassed())
870 {
871 EncodingSpecificOperations();
872 result = NOT(imm32);
873 if d == 15 then // Can only occur for ARM encoding
874 ALUWritePC(result); // setflags is always FALSE here
875 else
876 R[d] = result;
877 if setflags then
878 APSR.N = result<31>;
879 APSR.Z = IsZeroBit(result);
880 APSR.C = carry;
881 // APSR.V unchanged
882 }
883#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000884 bool success = false;
885 const uint32_t opcode = OpcodeAsUnsigned (&success);
886 if (!success)
887 return false;
888
889 if (ConditionPassed())
890 {
891 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000892 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
893 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000894 bool setflags;
895 switch (encoding) {
896 case eEncodingT1:
897 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000898 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000899 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000900 break;
901 case eEncodingA1:
902 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000904 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
905 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
906 // TODO: Emulate SUBS PC, LR and related instructions.
907 if (Rd == 15 && setflags)
908 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000909 break;
910 default:
911 return false;
912 }
913 uint32_t result = ~imm32;
914
915 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000916 EmulateInstruction::Context context;
917 context.type = EmulateInstruction::eContextImmediate;
918 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000919
Johnny Chen10530c22011-02-17 22:37:12 +0000920 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000921 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000922 }
923 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000924}
925
Johnny Chend642a6a2011-02-22 01:01:03 +0000926// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
927// It can optionally update the condition flags based on the result.
928bool
929EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
930{
931#if 0
932 // ARM pseudo code...
933 if (ConditionPassed())
934 {
935 EncodingSpecificOperations();
936 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
937 result = NOT(shifted);
938 if d == 15 then // Can only occur for ARM encoding
939 ALUWritePC(result); // setflags is always FALSE here
940 else
941 R[d] = result;
942 if setflags then
943 APSR.N = result<31>;
944 APSR.Z = IsZeroBit(result);
945 APSR.C = carry;
946 // APSR.V unchanged
947 }
948#endif
949
950 bool success = false;
951 const uint32_t opcode = OpcodeAsUnsigned (&success);
952 if (!success)
953 return false;
954
955 if (ConditionPassed())
956 {
957 uint32_t Rm; // the source register
958 uint32_t Rd; // the destination register
959 ARM_ShifterType shift_t;
960 uint32_t shift_n; // the shift applied to the value read from Rm
961 bool setflags;
962 uint32_t carry; // the carry bit after the shift operation
963 switch (encoding) {
964 case eEncodingT1:
965 Rd = Bits32(opcode, 2, 0);
966 Rm = Bits32(opcode, 5, 3);
967 setflags = !InITBlock();
968 shift_t = SRType_LSL;
969 shift_n = 0;
970 if (InITBlock())
971 return false;
972 break;
973 case eEncodingT2:
974 Rd = Bits32(opcode, 11, 8);
975 Rm = Bits32(opcode, 3, 0);
976 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000977 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000978 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000979 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000980 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000981 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000982 case eEncodingA1:
983 Rd = Bits32(opcode, 15, 12);
984 Rm = Bits32(opcode, 3, 0);
985 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000986 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000987 break;
988 default:
989 return false;
990 }
991 uint32_t value = ReadCoreReg(Rm, &success);
992 if (!success)
993 return false;
994
995 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
996 uint32_t result = ~shifted;
997
998 // The context specifies that an immediate is to be moved into Rd.
999 EmulateInstruction::Context context;
1000 context.type = EmulateInstruction::eContextImmediate;
1001 context.SetNoArgs ();
1002
1003 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1004 return false;
1005 }
1006 return true;
1007}
1008
Johnny Chen788e0552011-01-27 22:52:23 +00001009// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1010// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001012EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001013{
1014#if 0
1015 // ARM pseudo code...
1016 if (ConditionPassed())
1017 {
1018 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1019 base = Align(PC,4);
1020 address = if add then (base + imm32) else (base - imm32);
1021 data = MemU[address,4];
1022 if t == 15 then
1023 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1024 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1025 R[t] = data;
1026 else // Can only apply before ARMv7
1027 if CurrentInstrSet() == InstrSet_ARM then
1028 R[t] = ROR(data, 8*UInt(address<1:0>));
1029 else
1030 R[t] = bits(32) UNKNOWN;
1031 }
1032#endif
1033
1034 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001035 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001036 if (!success)
1037 return false;
1038
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001039 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001040 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001041 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001042 if (!success)
1043 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001044
1045 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001046 EmulateInstruction::Context context;
1047 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1048 Register pc_reg;
1049 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1050 context.SetRegisterPlusOffset (pc_reg, 0);
1051
Johnny Chenc9de9102011-02-11 19:12:30 +00001052 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001053 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001054 bool add; // +imm32 or -imm32?
1055 addr_t base; // the base address
1056 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001057 uint32_t data; // the literal data value from the PC relative load
1058 switch (encoding) {
1059 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001060 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001061 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001062 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001063 break;
1064 case eEncodingT2:
1065 Rt = Bits32(opcode, 15, 12);
1066 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1067 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001068 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001069 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001070 break;
1071 default:
1072 return false;
1073 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001074
Johnny Chene39f22d2011-02-19 01:36:13 +00001075 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001076 if (add)
1077 address = base + imm32;
1078 else
1079 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001080
1081 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001082 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001083 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001084 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001085
1086 if (Rt == 15)
1087 {
1088 if (Bits32(address, 1, 0) == 0)
1089 {
1090 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001091 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001092 return false;
1093 }
1094 else
1095 return false;
1096 }
1097 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1098 {
1099 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1100 return false;
1101 }
1102 else // We don't handle ARM for now.
1103 return false;
1104
1105 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001106 return false;
1107 }
1108 return true;
1109}
1110
Johnny Chen5b442b72011-01-27 19:34:30 +00001111// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001112// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001113bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001114EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001115{
1116#if 0
1117 // ARM pseudo code...
1118 if (ConditionPassed())
1119 {
1120 EncodingSpecificOperations();
1121 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1122 if d == 15 then // Can only occur for ARM encoding
1123 ALUWritePC(result); // setflags is always FALSE here
1124 else
1125 R[d] = result;
1126 if setflags then
1127 APSR.N = result<31>;
1128 APSR.Z = IsZeroBit(result);
1129 APSR.C = carry;
1130 APSR.V = overflow;
1131 }
1132#endif
1133
1134 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001135 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001136 if (!success)
1137 return false;
1138
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001139 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001140 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001141 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001142 if (!success)
1143 return false;
1144 uint32_t imm32; // the immediate operand
1145 switch (encoding) {
1146 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001147 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001148 break;
1149 default:
1150 return false;
1151 }
1152 addr_t sp_offset = imm32;
1153 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1154
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001155 EmulateInstruction::Context context;
1156 context.type = EmulateInstruction::eContextAdjustStackPointer;
1157 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001158
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001159 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001160 return false;
1161 }
1162 return true;
1163}
1164
1165// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001166// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001167bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001168EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001169{
1170#if 0
1171 // ARM pseudo code...
1172 if (ConditionPassed())
1173 {
1174 EncodingSpecificOperations();
1175 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1176 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1177 if d == 15 then
1178 ALUWritePC(result); // setflags is always FALSE here
1179 else
1180 R[d] = result;
1181 if setflags then
1182 APSR.N = result<31>;
1183 APSR.Z = IsZeroBit(result);
1184 APSR.C = carry;
1185 APSR.V = overflow;
1186 }
1187#endif
1188
1189 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001190 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001191 if (!success)
1192 return false;
1193
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001194 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001195 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001196 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001197 if (!success)
1198 return false;
1199 uint32_t Rm; // the second operand
1200 switch (encoding) {
1201 case eEncodingT2:
1202 Rm = Bits32(opcode, 6, 3);
1203 break;
1204 default:
1205 return false;
1206 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001207 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001208 if (!success)
1209 return false;
1210
1211 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1212
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001213 EmulateInstruction::Context context;
1214 context.type = EmulateInstruction::eContextAdjustStackPointer;
1215 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001216
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001218 return false;
1219 }
1220 return true;
1221}
1222
Johnny Chen9b8d7832011-02-02 01:13:56 +00001223// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1224// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1225// from Thumb to ARM.
1226// BLX (immediate)
1227bool
1228EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1229{
1230#if 0
1231 // ARM pseudo code...
1232 if (ConditionPassed())
1233 {
1234 EncodingSpecificOperations();
1235 if CurrentInstrSet() == InstrSet_ARM then
1236 LR = PC - 4;
1237 else
1238 LR = PC<31:1> : '1';
1239 if targetInstrSet == InstrSet_ARM then
1240 targetAddress = Align(PC,4) + imm32;
1241 else
1242 targetAddress = PC + imm32;
1243 SelectInstrSet(targetInstrSet);
1244 BranchWritePC(targetAddress);
1245 }
1246#endif
1247
1248 bool success = false;
1249 const uint32_t opcode = OpcodeAsUnsigned (&success);
1250 if (!success)
1251 return false;
1252
1253 if (ConditionPassed())
1254 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001255 EmulateInstruction::Context context;
1256 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001257 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001258 if (!success)
1259 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001260 addr_t lr; // next instruction address
1261 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001262 int32_t imm32; // PC-relative offset
1263 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001264 case eEncodingT1:
1265 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001266 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001267 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001268 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001269 uint32_t J1 = Bit32(opcode, 13);
1270 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001271 uint32_t imm11 = Bits32(opcode, 10, 0);
1272 uint32_t I1 = !(J1 ^ S);
1273 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001274 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001275 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001276 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001277 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001278 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001279 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001280 break;
1281 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001282 case eEncodingT2:
1283 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001284 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001285 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001286 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001287 uint32_t J1 = Bit32(opcode, 13);
1288 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 uint32_t imm10L = Bits32(opcode, 10, 1);
1290 uint32_t I1 = !(J1 ^ S);
1291 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001292 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001293 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001294 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001295 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001296 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001297 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001298 break;
1299 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001300 case eEncodingA1:
1301 lr = pc + 4; // return address
1302 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001303 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001305 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001306 case eEncodingA2:
1307 lr = pc + 4; // return address
1308 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001309 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001310 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 break;
1312 default:
1313 return false;
1314 }
1315 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1316 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001317 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001318 return false;
1319 }
1320 return true;
1321}
1322
1323// Branch with Link and Exchange (register) calls a subroutine at an address and
1324// instruction set specified by a register.
1325// BLX (register)
1326bool
1327EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1328{
1329#if 0
1330 // ARM pseudo code...
1331 if (ConditionPassed())
1332 {
1333 EncodingSpecificOperations();
1334 target = R[m];
1335 if CurrentInstrSet() == InstrSet_ARM then
1336 next_instr_addr = PC - 4;
1337 LR = next_instr_addr;
1338 else
1339 next_instr_addr = PC - 2;
1340 LR = next_instr_addr<31:1> : ‘1’;
1341 BXWritePC(target);
1342 }
1343#endif
1344
1345 bool success = false;
1346 const uint32_t opcode = OpcodeAsUnsigned (&success);
1347 if (!success)
1348 return false;
1349
1350 if (ConditionPassed())
1351 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001352 EmulateInstruction::Context context;
1353 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001354 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001355 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 if (!success)
1357 return false;
1358 uint32_t Rm; // the register with the target address
1359 switch (encoding) {
1360 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001361 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001362 Rm = Bits32(opcode, 6, 3);
1363 // if m == 15 then UNPREDICTABLE;
1364 if (Rm == 15)
1365 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001366 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001367 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001368 break;
1369 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001370 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001371 Rm = Bits32(opcode, 3, 0);
1372 // if m == 15 then UNPREDICTABLE;
1373 if (Rm == 15)
1374 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001375 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 default:
1377 return false;
1378 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001380 if (!success)
1381 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001382 Register dwarf_reg;
1383 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1384 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001385 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1386 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001387 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 return false;
1389 }
1390 return true;
1391}
1392
Johnny Chenab3b3512011-02-12 00:10:51 +00001393// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001394bool
1395EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1396{
1397#if 0
1398 // ARM pseudo code...
1399 if (ConditionPassed())
1400 {
1401 EncodingSpecificOperations();
1402 BXWritePC(R[m]);
1403 }
1404#endif
1405
1406 bool success = false;
1407 const uint32_t opcode = OpcodeAsUnsigned (&success);
1408 if (!success)
1409 return false;
1410
1411 if (ConditionPassed())
1412 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 EmulateInstruction::Context context;
1414 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001415 uint32_t Rm; // the register with the target address
1416 switch (encoding) {
1417 case eEncodingT1:
1418 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001419 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001420 return false;
1421 break;
1422 case eEncodingA1:
1423 Rm = Bits32(opcode, 3, 0);
1424 break;
1425 default:
1426 return false;
1427 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001428 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001429 if (!success)
1430 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001431
1432 Register dwarf_reg;
1433 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001434 context.SetRegister (dwarf_reg);
1435 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001436 return false;
1437 }
1438 return true;
1439}
1440
Johnny Chen59e6ab72011-02-24 21:01:20 +00001441// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1442// address and instruction set specified by a register as though it were a BX instruction.
1443//
1444// TODO: Emulate Jazelle architecture?
1445// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1446bool
1447EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1448{
1449#if 0
1450 // ARM pseudo code...
1451 if (ConditionPassed())
1452 {
1453 EncodingSpecificOperations();
1454 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1455 BXWritePC(R[m]);
1456 else
1457 if JazelleAcceptsExecution() then
1458 SwitchToJazelleExecution();
1459 else
1460 SUBARCHITECTURE_DEFINED handler call;
1461 }
1462#endif
1463
1464 bool success = false;
1465 const uint32_t opcode = OpcodeAsUnsigned (&success);
1466 if (!success)
1467 return false;
1468
1469 if (ConditionPassed())
1470 {
1471 EmulateInstruction::Context context;
1472 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1473 uint32_t Rm; // the register with the target address
1474 switch (encoding) {
1475 case eEncodingT1:
1476 Rm = Bits32(opcode, 19, 16);
1477 if (BadReg(Rm))
1478 return false;
1479 if (InITBlock() && !LastInITBlock())
1480 return false;
1481 break;
1482 case eEncodingA1:
1483 Rm = Bits32(opcode, 3, 0);
1484 if (Rm == 15)
1485 return false;
1486 break;
1487 default:
1488 return false;
1489 }
1490 addr_t target = ReadCoreReg (Rm, &success);
1491 if (!success)
1492 return false;
1493
1494 Register dwarf_reg;
1495 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1496 context.SetRegister (dwarf_reg);
1497 if (!BXWritePC(context, target))
1498 return false;
1499 }
1500 return true;
1501}
1502
Johnny Chen0d0148e2011-01-28 02:26:08 +00001503// Set r7 to point to some ip offset.
1504// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001505bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001506EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001507{
1508#if 0
1509 // ARM pseudo code...
1510 if (ConditionPassed())
1511 {
1512 EncodingSpecificOperations();
1513 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1514 if d == 15 then // Can only occur for ARM encoding
1515 ALUWritePC(result); // setflags is always FALSE here
1516 else
1517 R[d] = result;
1518 if setflags then
1519 APSR.N = result<31>;
1520 APSR.Z = IsZeroBit(result);
1521 APSR.C = carry;
1522 APSR.V = overflow;
1523 }
1524#endif
1525
1526 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001527 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001528 if (!success)
1529 return false;
1530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001531 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001532 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001533 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001534 if (!success)
1535 return false;
1536 uint32_t imm32;
1537 switch (encoding) {
1538 case eEncodingA1:
1539 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1540 break;
1541 default:
1542 return false;
1543 }
1544 addr_t ip_offset = imm32;
1545 addr_t addr = ip - ip_offset; // the adjusted ip value
1546
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001547 EmulateInstruction::Context context;
1548 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1549 Register dwarf_reg;
1550 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1551 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001552
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001554 return false;
1555 }
1556 return true;
1557}
1558
1559// Set ip to point to some stack offset.
1560// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001561bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001562EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001563{
1564#if 0
1565 // ARM pseudo code...
1566 if (ConditionPassed())
1567 {
1568 EncodingSpecificOperations();
1569 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1570 if d == 15 then // Can only occur for ARM encoding
1571 ALUWritePC(result); // setflags is always FALSE here
1572 else
1573 R[d] = result;
1574 if setflags then
1575 APSR.N = result<31>;
1576 APSR.Z = IsZeroBit(result);
1577 APSR.C = carry;
1578 APSR.V = overflow;
1579 }
1580#endif
1581
1582 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001583 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001584 if (!success)
1585 return false;
1586
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001587 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001588 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001589 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001590 if (!success)
1591 return false;
1592 uint32_t imm32;
1593 switch (encoding) {
1594 case eEncodingA1:
1595 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1596 break;
1597 default:
1598 return false;
1599 }
1600 addr_t sp_offset = imm32;
1601 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1602
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001603 EmulateInstruction::Context context;
1604 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1605 Register dwarf_reg;
1606 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1607 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001608
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001609 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001610 return false;
1611 }
1612 return true;
1613}
1614
Johnny Chenc9e747f2011-02-23 01:55:07 +00001615// This instruction subtracts an immediate value from the SP value, and writes
1616// the result to the destination register.
1617//
1618// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001619bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001620EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001621{
1622#if 0
1623 // ARM pseudo code...
1624 if (ConditionPassed())
1625 {
1626 EncodingSpecificOperations();
1627 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001628 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001629 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001630 else
1631 R[d] = result;
1632 if setflags then
1633 APSR.N = result<31>;
1634 APSR.Z = IsZeroBit(result);
1635 APSR.C = carry;
1636 APSR.V = overflow;
1637 }
1638#endif
1639
1640 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001642 if (!success)
1643 return false;
1644
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001645 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001646 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001647 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001648 if (!success)
1649 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001650
1651 uint32_t Rd;
1652 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001653 uint32_t imm32;
1654 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001655 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001656 Rd = 13;
1657 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001658 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001659 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001660 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001661 Rd = Bits32(opcode, 11, 8);
1662 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001663 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001664 if (Rd == 15 && setflags)
1665 return EmulateCMPImm(eEncodingT2);
1666 if (Rd == 15 && !setflags)
1667 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001668 break;
1669 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001670 Rd = Bits32(opcode, 11, 8);
1671 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001672 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001673 if (Rd == 15)
1674 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001675 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001676 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001677 Rd = Bits32(opcode, 15, 12);
1678 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001679 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001680 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1681 // TODO: Emulate SUBS PC, LR and related instructions.
1682 if (Rd == 15 && setflags)
1683 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001684 break;
1685 default:
1686 return false;
1687 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001688 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1689
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001690 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001691 if (Rd == 13)
1692 {
1693 context.type = EmulateInstruction::eContextAdjustStackPointer;
1694 context.SetImmediateSigned (-imm32); // the stack pointer offset
1695 }
1696 else
1697 {
1698 context.type = EmulateInstruction::eContextImmediate;
1699 context.SetNoArgs ();
1700 }
1701
1702 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001703 return false;
1704 }
1705 return true;
1706}
1707
Johnny Chen08c25e82011-01-31 18:02:28 +00001708// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001709bool
1710EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001711{
1712#if 0
1713 // ARM pseudo code...
1714 if (ConditionPassed())
1715 {
1716 EncodingSpecificOperations();
1717 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1718 address = if index then offset_addr else R[n];
1719 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1720 if wback then R[n] = offset_addr;
1721 }
1722#endif
1723
1724 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001725 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001726 if (!success)
1727 return false;
1728
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001729 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001730 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001731 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001732 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001733 if (!success)
1734 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001735 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001736 uint32_t imm12;
1737 switch (encoding) {
1738 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001739 Rt = Bits32(opcode, 15, 12);
1740 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001741 break;
1742 default:
1743 return false;
1744 }
1745 addr_t sp_offset = imm12;
1746 addr_t addr = sp - sp_offset;
1747
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001748 EmulateInstruction::Context context;
1749 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1750 Register dwarf_reg;
1751 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001752 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001753 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001754 dwarf_reg.num = dwarf_r0 + Rt;
1755 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001756 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001757 if (!success)
1758 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001759 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001760 return false;
1761 }
1762 else
1763 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001764 dwarf_reg.num = dwarf_pc;
1765 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001766 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001767 if (!success)
1768 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001769 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001770 return false;
1771 }
1772
1773 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001774 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001775
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001776 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001777 return false;
1778 }
1779 return true;
1780}
1781
Johnny Chen08c25e82011-01-31 18:02:28 +00001782// Vector Push stores multiple extension registers to the stack.
1783// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001784bool
1785EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001786{
1787#if 0
1788 // ARM pseudo code...
1789 if (ConditionPassed())
1790 {
1791 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1792 address = SP - imm32;
1793 SP = SP - imm32;
1794 if single_regs then
1795 for r = 0 to regs-1
1796 MemA[address,4] = S[d+r]; address = address+4;
1797 else
1798 for r = 0 to regs-1
1799 // Store as two word-aligned words in the correct order for current endianness.
1800 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1801 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1802 address = address+8;
1803 }
1804#endif
1805
1806 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001807 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001808 if (!success)
1809 return false;
1810
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001811 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001812 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001813 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001814 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001815 if (!success)
1816 return false;
1817 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001818 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001819 uint32_t imm32; // stack offset
1820 uint32_t regs; // number of registers
1821 switch (encoding) {
1822 case eEncodingT1:
1823 case eEncodingA1:
1824 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001825 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001826 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1827 // If UInt(imm8) is odd, see "FSTMX".
1828 regs = Bits32(opcode, 7, 0) / 2;
1829 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1830 if (regs == 0 || regs > 16 || (d + regs) > 32)
1831 return false;
1832 break;
1833 case eEncodingT2:
1834 case eEncodingA2:
1835 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001836 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001837 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1838 regs = Bits32(opcode, 7, 0);
1839 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1840 if (regs == 0 || regs > 16 || (d + regs) > 32)
1841 return false;
1842 break;
1843 default:
1844 return false;
1845 }
1846 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1847 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1848 addr_t sp_offset = imm32;
1849 addr_t addr = sp - sp_offset;
1850 uint32_t i;
1851
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001852 EmulateInstruction::Context context;
1853 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1854 Register dwarf_reg;
1855 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001856 for (i=d; i<regs; ++i)
1857 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001858 dwarf_reg.num = start_reg + i;
1859 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001860 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001861 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001862 if (!success)
1863 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001864 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001865 return false;
1866 addr += reg_byte_size;
1867 }
1868
1869 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001870 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001871
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001872 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001873 return false;
1874 }
1875 return true;
1876}
1877
Johnny Chen587a0a42011-02-01 18:35:28 +00001878// Vector Pop loads multiple extension registers from the stack.
1879// It also updates SP to point just above the loaded data.
1880bool
1881EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1882{
1883#if 0
1884 // ARM pseudo code...
1885 if (ConditionPassed())
1886 {
1887 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1888 address = SP;
1889 SP = SP + imm32;
1890 if single_regs then
1891 for r = 0 to regs-1
1892 S[d+r] = MemA[address,4]; address = address+4;
1893 else
1894 for r = 0 to regs-1
1895 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1896 // Combine the word-aligned words in the correct order for current endianness.
1897 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1898 }
1899#endif
1900
1901 bool success = false;
1902 const uint32_t opcode = OpcodeAsUnsigned (&success);
1903 if (!success)
1904 return false;
1905
1906 if (ConditionPassed())
1907 {
1908 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001909 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001910 if (!success)
1911 return false;
1912 bool single_regs;
1913 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1914 uint32_t imm32; // stack offset
1915 uint32_t regs; // number of registers
1916 switch (encoding) {
1917 case eEncodingT1:
1918 case eEncodingA1:
1919 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001920 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001921 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1922 // If UInt(imm8) is odd, see "FLDMX".
1923 regs = Bits32(opcode, 7, 0) / 2;
1924 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1925 if (regs == 0 || regs > 16 || (d + regs) > 32)
1926 return false;
1927 break;
1928 case eEncodingT2:
1929 case eEncodingA2:
1930 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001931 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001932 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1933 regs = Bits32(opcode, 7, 0);
1934 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1935 if (regs == 0 || regs > 16 || (d + regs) > 32)
1936 return false;
1937 break;
1938 default:
1939 return false;
1940 }
1941 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1942 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1943 addr_t sp_offset = imm32;
1944 addr_t addr = sp;
1945 uint32_t i;
1946 uint64_t data; // uint64_t to accomodate 64-bit registers.
1947
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001948 EmulateInstruction::Context context;
1949 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1950 Register dwarf_reg;
1951 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001952 for (i=d; i<regs; ++i)
1953 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001954 dwarf_reg.num = start_reg + i;
1955 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001956 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001957 if (!success)
1958 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001959 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001960 return false;
1961 addr += reg_byte_size;
1962 }
1963
1964 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001965 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001966
1967 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1968 return false;
1969 }
1970 return true;
1971}
1972
Johnny Chenb77be412011-02-04 00:40:18 +00001973// SVC (previously SWI)
1974bool
1975EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1976{
1977#if 0
1978 // ARM pseudo code...
1979 if (ConditionPassed())
1980 {
1981 EncodingSpecificOperations();
1982 CallSupervisor();
1983 }
1984#endif
1985
1986 bool success = false;
1987 const uint32_t opcode = OpcodeAsUnsigned (&success);
1988 if (!success)
1989 return false;
1990
1991 if (ConditionPassed())
1992 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001993 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001994 addr_t lr; // next instruction address
1995 if (!success)
1996 return false;
1997 uint32_t imm32; // the immediate constant
1998 uint32_t mode; // ARM or Thumb mode
1999 switch (encoding) {
2000 case eEncodingT1:
2001 lr = (pc + 2) | 1u; // return address
2002 imm32 = Bits32(opcode, 7, 0);
2003 mode = eModeThumb;
2004 break;
2005 case eEncodingA1:
2006 lr = pc + 4; // return address
2007 imm32 = Bits32(opcode, 23, 0);
2008 mode = eModeARM;
2009 break;
2010 default:
2011 return false;
2012 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002013
2014 EmulateInstruction::Context context;
2015 context.type = EmulateInstruction::eContextSupervisorCall;
2016 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002017 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2018 return false;
2019 }
2020 return true;
2021}
2022
Johnny Chenc315f862011-02-05 00:46:10 +00002023// If Then makes up to four following instructions (the IT block) conditional.
2024bool
2025EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2026{
2027#if 0
2028 // ARM pseudo code...
2029 EncodingSpecificOperations();
2030 ITSTATE.IT<7:0> = firstcond:mask;
2031#endif
2032
2033 bool success = false;
2034 const uint32_t opcode = OpcodeAsUnsigned (&success);
2035 if (!success)
2036 return false;
2037
2038 m_it_session.InitIT(Bits32(opcode, 7, 0));
2039 return true;
2040}
2041
Johnny Chen3b620b32011-02-07 20:11:47 +00002042// Branch causes a branch to a target address.
2043bool
2044EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2045{
2046#if 0
2047 // ARM pseudo code...
2048 if (ConditionPassed())
2049 {
2050 EncodingSpecificOperations();
2051 BranchWritePC(PC + imm32);
2052 }
2053#endif
2054
2055 bool success = false;
2056 const uint32_t opcode = OpcodeAsUnsigned (&success);
2057 if (!success)
2058 return false;
2059
Johnny Chen9ee056b2011-02-08 00:06:35 +00002060 if (ConditionPassed())
2061 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002062 EmulateInstruction::Context context;
2063 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002064 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002065 if (!success)
2066 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002067 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002068 int32_t imm32; // PC-relative offset
2069 switch (encoding) {
2070 case eEncodingT1:
2071 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2072 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002073 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002074 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002075 break;
2076 case eEncodingT2:
2077 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002078 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002079 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002080 break;
2081 case eEncodingT3:
2082 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2083 {
Johnny Chenbd599902011-02-10 21:39:01 +00002084 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002085 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002086 uint32_t J1 = Bit32(opcode, 13);
2087 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002088 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002089 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002090 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002091 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002092 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002093 break;
2094 }
2095 case eEncodingT4:
2096 {
Johnny Chenbd599902011-02-10 21:39:01 +00002097 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002098 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002099 uint32_t J1 = Bit32(opcode, 13);
2100 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002101 uint32_t imm11 = Bits32(opcode, 10, 0);
2102 uint32_t I1 = !(J1 ^ S);
2103 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002104 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002105 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002106 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002107 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002108 break;
2109 }
2110 case eEncodingA1:
2111 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002112 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002113 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002114 break;
2115 default:
2116 return false;
2117 }
2118 if (!BranchWritePC(context, target))
2119 return false;
2120 }
2121 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002122}
2123
Johnny Chen53ebab72011-02-08 23:21:57 +00002124// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2125// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2126// CBNZ, CBZ
2127bool
2128EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2129{
2130#if 0
2131 // ARM pseudo code...
2132 EncodingSpecificOperations();
2133 if nonzero ^ IsZero(R[n]) then
2134 BranchWritePC(PC + imm32);
2135#endif
2136
2137 bool success = false;
2138 const uint32_t opcode = OpcodeAsUnsigned (&success);
2139 if (!success)
2140 return false;
2141
2142 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002143 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002144 if (!success)
2145 return false;
2146
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002147 EmulateInstruction::Context context;
2148 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002149 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002150 if (!success)
2151 return false;
2152
2153 addr_t target; // target address
2154 uint32_t imm32; // PC-relative offset to branch forward
2155 bool nonzero;
2156 switch (encoding) {
2157 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002158 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002159 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002160 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002161 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002162 break;
2163 default:
2164 return false;
2165 }
2166 if (nonzero ^ (reg_val == 0))
2167 if (!BranchWritePC(context, target))
2168 return false;
2169
2170 return true;
2171}
2172
Johnny Chen60299ec2011-02-17 19:34:27 +00002173// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2174// A base register provides a pointer to the table, and a second register supplies an index into the table.
2175// The branch length is twice the value of the byte returned from the table.
2176//
2177// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2178// A base register provides a pointer to the table, and a second register supplies an index into the table.
2179// The branch length is twice the value of the halfword returned from the table.
2180// TBB, TBH
2181bool
2182EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2183{
2184#if 0
2185 // ARM pseudo code...
2186 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2187 if is_tbh then
2188 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2189 else
2190 halfwords = UInt(MemU[R[n]+R[m], 1]);
2191 BranchWritePC(PC + 2*halfwords);
2192#endif
2193
2194 bool success = false;
2195 const uint32_t opcode = OpcodeAsUnsigned (&success);
2196 if (!success)
2197 return false;
2198
2199 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2200 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2201 bool is_tbh; // true if table branch halfword
2202 switch (encoding) {
2203 case eEncodingT1:
2204 Rn = Bits32(opcode, 19, 16);
2205 Rm = Bits32(opcode, 3, 0);
2206 is_tbh = BitIsSet(opcode, 4);
2207 if (Rn == 13 || BadReg(Rm))
2208 return false;
2209 if (InITBlock() && !LastInITBlock())
2210 return false;
2211 break;
2212 default:
2213 return false;
2214 }
2215
2216 // Read the address of the table from the operand register Rn.
2217 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002218 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002219 if (!success)
2220 return false;
2221
2222 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002223 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002224 if (!success)
2225 return false;
2226
2227 // the offsetted table address
2228 addr_t addr = base + (is_tbh ? index*2 : index);
2229
2230 // PC-relative offset to branch forward
2231 EmulateInstruction::Context context;
2232 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002233 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002234 if (!success)
2235 return false;
2236
Johnny Chene39f22d2011-02-19 01:36:13 +00002237 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002238 if (!success)
2239 return false;
2240
2241 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002242 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002243 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2244 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2245
2246 if (!BranchWritePC(context, target))
2247 return false;
2248
2249 return true;
2250}
2251
Caroline Ticedcc11b32011-03-02 23:57:02 +00002252// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2253// It can optionally update the condition flags based on the result.
2254bool
2255EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2256{
2257#if 0
2258 if ConditionPassed() then
2259 EncodingSpecificOperations();
2260 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2261 R[d] = result;
2262 if setflags then
2263 APSR.N = result<31>;
2264 APSR.Z = IsZeroBit(result);
2265 APSR.C = carry;
2266 APSR.V = overflow;
2267#endif
2268
2269 bool success = false;
2270 const uint32_t opcode = OpcodeAsUnsigned (&success);
2271 if (!success)
2272 return false;
2273
2274 if (ConditionPassed())
2275 {
2276 uint32_t d;
2277 uint32_t n;
2278 bool setflags;
2279 uint32_t imm32;
2280 uint32_t carry_out;
2281
2282 //EncodingSpecificOperations();
2283 switch (encoding)
2284 {
2285 case eEncodingT1:
2286 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2287 d = Bits32 (opcode, 2, 0);
2288 n = Bits32 (opcode, 5, 3);
2289 setflags = !InITBlock();
2290 imm32 = Bits32 (opcode, 8,6);
2291
2292 break;
2293
2294 case eEncodingT2:
2295 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2296 d = Bits32 (opcode, 10, 8);
2297 n = Bits32 (opcode, 10, 8);
2298 setflags = !InITBlock();
2299 imm32 = Bits32 (opcode, 7, 0);
2300
2301 break;
2302
2303 case eEncodingT3:
2304 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2305 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2306 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2307 d = Bits32 (opcode, 11, 8);
2308 n = Bits32 (opcode, 19, 16);
2309 setflags = BitIsSet (opcode, 20);
2310 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2311
2312 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2313 if (BadReg (d) || (n == 15))
2314 return false;
2315
2316 break;
2317
2318 case eEncodingT4:
2319 {
2320 // if Rn == ’1111’ then SEE ADR;
2321 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2322 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2323 d = Bits32 (opcode, 11, 8);
2324 n = Bits32 (opcode, 19, 16);
2325 setflags = false;
2326 uint32_t i = Bit32 (opcode, 26);
2327 uint32_t imm3 = Bits32 (opcode, 14, 12);
2328 uint32_t imm8 = Bits32 (opcode, 7, 0);
2329 imm32 = (i << 11) | (imm3 << 8) | imm8;
2330
2331 // if BadReg(d) then UNPREDICTABLE;
2332 if (BadReg (d))
2333 return false;
2334
2335 break;
2336 }
2337 default:
2338 return false;
2339 }
2340
2341 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2342 if (!success)
2343 return false;
2344
2345 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2346 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2347
2348 Register reg_n;
2349 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2350
2351 EmulateInstruction::Context context;
2352 context.type = eContextAddition;
2353 context.SetRegisterPlusOffset (reg_n, imm32);
2354
2355 //R[d] = result;
2356 //if setflags then
2357 //APSR.N = result<31>;
2358 //APSR.Z = IsZeroBit(result);
2359 //APSR.C = carry;
2360 //APSR.V = overflow;
2361 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2362 return false;
2363
2364 }
2365 return true;
2366}
2367
Johnny Chen8fa20592011-02-18 01:22:22 +00002368// This instruction adds an immediate value to a register value, and writes the result to the destination
2369// register. It can optionally update the condition flags based on the result.
2370bool
2371EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2372{
2373#if 0
2374 // ARM pseudo code...
2375 if ConditionPassed() then
2376 EncodingSpecificOperations();
2377 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2378 if d == 15 then
2379 ALUWritePC(result); // setflags is always FALSE here
2380 else
2381 R[d] = result;
2382 if setflags then
2383 APSR.N = result<31>;
2384 APSR.Z = IsZeroBit(result);
2385 APSR.C = carry;
2386 APSR.V = overflow;
2387#endif
2388
2389 bool success = false;
2390 const uint32_t opcode = OpcodeAsUnsigned (&success);
2391 if (!success)
2392 return false;
2393
2394 if (ConditionPassed())
2395 {
2396 uint32_t Rd, Rn;
2397 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2398 bool setflags;
2399 switch (encoding)
2400 {
2401 case eEncodingA1:
2402 Rd = Bits32(opcode, 15, 12);
2403 Rn = Bits32(opcode, 19, 16);
2404 setflags = BitIsSet(opcode, 20);
2405 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2406 break;
2407 default:
2408 return false;
2409 }
2410
Johnny Chen8fa20592011-02-18 01:22:22 +00002411 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002412 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002413 if (!success)
2414 return false;
2415
2416 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2417
2418 EmulateInstruction::Context context;
2419 context.type = EmulateInstruction::eContextImmediate;
2420 context.SetNoArgs ();
2421
2422 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2423 return false;
2424 }
2425 return true;
2426}
2427
Johnny Chend761dcf2011-02-17 22:03:29 +00002428// This instruction adds a register value and an optionally-shifted register value, and writes the result
2429// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002430bool
Johnny Chen9f687722011-02-18 00:02:28 +00002431EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002432{
2433#if 0
2434 // ARM pseudo code...
2435 if ConditionPassed() then
2436 EncodingSpecificOperations();
2437 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2438 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2439 if d == 15 then
2440 ALUWritePC(result); // setflags is always FALSE here
2441 else
2442 R[d] = result;
2443 if setflags then
2444 APSR.N = result<31>;
2445 APSR.Z = IsZeroBit(result);
2446 APSR.C = carry;
2447 APSR.V = overflow;
2448#endif
2449
2450 bool success = false;
2451 const uint32_t opcode = OpcodeAsUnsigned (&success);
2452 if (!success)
2453 return false;
2454
2455 if (ConditionPassed())
2456 {
2457 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002458 ARM_ShifterType shift_t;
2459 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002460 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002461 switch (encoding)
2462 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002463 case eEncodingT1:
2464 Rd = Bits32(opcode, 2, 0);
2465 Rn = Bits32(opcode, 5, 3);
2466 Rm = Bits32(opcode, 8, 6);
2467 setflags = !InITBlock();
2468 shift_t = SRType_LSL;
2469 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002470 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002471 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002472 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002473 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002474 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002475 shift_t = SRType_LSL;
2476 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002477 if (Rn == 15 && Rm == 15)
2478 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002479 if (Rd == 15 && InITBlock() && !LastInITBlock())
2480 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002481 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002482 case eEncodingA1:
2483 Rd = Bits32(opcode, 15, 12);
2484 Rn = Bits32(opcode, 19, 16);
2485 Rm = Bits32(opcode, 3, 0);
2486 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002487 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002488 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002489 default:
2490 return false;
2491 }
2492
Johnny Chen26863dc2011-02-09 23:43:29 +00002493 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002494 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002495 if (!success)
2496 return false;
2497
2498 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002499 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002500 if (!success)
2501 return false;
2502
Johnny Chene97c0d52011-02-18 19:32:20 +00002503 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002504 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002505
2506 EmulateInstruction::Context context;
2507 context.type = EmulateInstruction::eContextImmediate;
2508 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002509
Johnny Chen10530c22011-02-17 22:37:12 +00002510 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002511 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002512 }
2513 return true;
2514}
2515
Johnny Chen34075cb2011-02-22 01:56:31 +00002516// Compare Negative (immediate) adds a register value and an immediate value.
2517// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002518bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002519EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2520{
2521#if 0
2522 // ARM pseudo code...
2523 if ConditionPassed() then
2524 EncodingSpecificOperations();
2525 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2526 APSR.N = result<31>;
2527 APSR.Z = IsZeroBit(result);
2528 APSR.C = carry;
2529 APSR.V = overflow;
2530#endif
2531
2532 bool success = false;
2533 const uint32_t opcode = OpcodeAsUnsigned (&success);
2534 if (!success)
2535 return false;
2536
2537 uint32_t Rn; // the first operand
2538 uint32_t imm32; // the immediate value to be compared with
2539 switch (encoding) {
2540 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002541 Rn = Bits32(opcode, 19, 16);
2542 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2543 if (Rn == 15)
2544 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002545 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002546 case eEncodingA1:
2547 Rn = Bits32(opcode, 19, 16);
2548 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2549 break;
2550 default:
2551 return false;
2552 }
2553 // Read the register value from the operand register Rn.
2554 uint32_t reg_val = ReadCoreReg(Rn, &success);
2555 if (!success)
2556 return false;
2557
Johnny Chen078fbc62011-02-22 19:48:22 +00002558 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002559
2560 EmulateInstruction::Context context;
2561 context.type = EmulateInstruction::eContextImmediate;
2562 context.SetNoArgs ();
2563 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2564 return false;
2565
2566 return true;
2567}
2568
2569// Compare Negative (register) adds a register value and an optionally-shifted register value.
2570// It updates the condition flags based on the result, and discards the result.
2571bool
2572EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2573{
2574#if 0
2575 // ARM pseudo code...
2576 if ConditionPassed() then
2577 EncodingSpecificOperations();
2578 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2579 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2580 APSR.N = result<31>;
2581 APSR.Z = IsZeroBit(result);
2582 APSR.C = carry;
2583 APSR.V = overflow;
2584#endif
2585
2586 bool success = false;
2587 const uint32_t opcode = OpcodeAsUnsigned (&success);
2588 if (!success)
2589 return false;
2590
2591 uint32_t Rn; // the first operand
2592 uint32_t Rm; // the second operand
2593 ARM_ShifterType shift_t;
2594 uint32_t shift_n; // the shift applied to the value read from Rm
2595 switch (encoding) {
2596 case eEncodingT1:
2597 Rn = Bits32(opcode, 2, 0);
2598 Rm = Bits32(opcode, 5, 3);
2599 shift_t = SRType_LSL;
2600 shift_n = 0;
2601 break;
2602 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002603 Rn = Bits32(opcode, 19, 16);
2604 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002605 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002606 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2607 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002608 return false;
2609 break;
2610 case eEncodingA1:
2611 Rn = Bits32(opcode, 19, 16);
2612 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002613 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002614 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002615 default:
2616 return false;
2617 }
2618 // Read the register value from register Rn.
2619 uint32_t val1 = ReadCoreReg(Rn, &success);
2620 if (!success)
2621 return false;
2622
2623 // Read the register value from register Rm.
2624 uint32_t val2 = ReadCoreReg(Rm, &success);
2625 if (!success)
2626 return false;
2627
2628 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002629 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002630
2631 EmulateInstruction::Context context;
2632 context.type = EmulateInstruction::eContextImmediate;
2633 context.SetNoArgs();
2634 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2635 return false;
2636
2637 return true;
2638}
2639
2640// Compare (immediate) subtracts an immediate value from a register value.
2641// It updates the condition flags based on the result, and discards the result.
2642bool
2643EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002644{
2645#if 0
2646 // ARM pseudo code...
2647 if ConditionPassed() then
2648 EncodingSpecificOperations();
2649 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2650 APSR.N = result<31>;
2651 APSR.Z = IsZeroBit(result);
2652 APSR.C = carry;
2653 APSR.V = overflow;
2654#endif
2655
2656 bool success = false;
2657 const uint32_t opcode = OpcodeAsUnsigned (&success);
2658 if (!success)
2659 return false;
2660
2661 uint32_t Rn; // the first operand
2662 uint32_t imm32; // the immediate value to be compared with
2663 switch (encoding) {
2664 case eEncodingT1:
2665 Rn = Bits32(opcode, 10, 8);
2666 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002667 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002668 case eEncodingT2:
2669 Rn = Bits32(opcode, 19, 16);
2670 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2671 if (Rn == 15)
2672 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002673 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002674 case eEncodingA1:
2675 Rn = Bits32(opcode, 19, 16);
2676 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002677 break;
2678 default:
2679 return false;
2680 }
2681 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002682 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002683 if (!success)
2684 return false;
2685
Johnny Chen10530c22011-02-17 22:37:12 +00002686 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2687
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002688 EmulateInstruction::Context context;
2689 context.type = EmulateInstruction::eContextImmediate;
2690 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002691 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2692 return false;
2693
Johnny Chend4dc4442011-02-11 02:02:56 +00002694 return true;
2695}
2696
Johnny Chen34075cb2011-02-22 01:56:31 +00002697// Compare (register) subtracts an optionally-shifted register value from a register value.
2698// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002699bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002700EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002701{
2702#if 0
2703 // ARM pseudo code...
2704 if ConditionPassed() then
2705 EncodingSpecificOperations();
2706 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2707 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2708 APSR.N = result<31>;
2709 APSR.Z = IsZeroBit(result);
2710 APSR.C = carry;
2711 APSR.V = overflow;
2712#endif
2713
2714 bool success = false;
2715 const uint32_t opcode = OpcodeAsUnsigned (&success);
2716 if (!success)
2717 return false;
2718
2719 uint32_t Rn; // the first operand
2720 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002721 ARM_ShifterType shift_t;
2722 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002723 switch (encoding) {
2724 case eEncodingT1:
2725 Rn = Bits32(opcode, 2, 0);
2726 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002727 shift_t = SRType_LSL;
2728 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002729 break;
2730 case eEncodingT2:
2731 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2732 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002733 shift_t = SRType_LSL;
2734 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002735 if (Rn < 8 && Rm < 8)
2736 return false;
2737 if (Rn == 15 || Rm == 15)
2738 return false;
2739 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002740 case eEncodingA1:
2741 Rn = Bits32(opcode, 19, 16);
2742 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002743 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002744 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002745 default:
2746 return false;
2747 }
2748 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002749 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002750 if (!success)
2751 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002752
Johnny Chene4a4d302011-02-11 21:53:58 +00002753 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002754 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002755 if (!success)
2756 return false;
2757
Johnny Chen34075cb2011-02-22 01:56:31 +00002758 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2759 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002760
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002761 EmulateInstruction::Context context;
2762 context.type = EmulateInstruction::eContextImmediate;
2763 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002764 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2765 return false;
2766
Johnny Chene4a4d302011-02-11 21:53:58 +00002767 return true;
2768}
2769
Johnny Chen82f16aa2011-02-15 20:10:55 +00002770// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2771// shifting in copies of its sign bit, and writes the result to the destination register. It can
2772// optionally update the condition flags based on the result.
2773bool
2774EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2775{
2776#if 0
2777 // ARM pseudo code...
2778 if ConditionPassed() then
2779 EncodingSpecificOperations();
2780 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2781 if d == 15 then // Can only occur for ARM encoding
2782 ALUWritePC(result); // setflags is always FALSE here
2783 else
2784 R[d] = result;
2785 if setflags then
2786 APSR.N = result<31>;
2787 APSR.Z = IsZeroBit(result);
2788 APSR.C = carry;
2789 // APSR.V unchanged
2790#endif
2791
Johnny Chen41a0a152011-02-16 01:27:54 +00002792 return EmulateShiftImm(encoding, SRType_ASR);
2793}
2794
2795// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2796// shifting in copies of its sign bit, and writes the result to the destination register.
2797// The variable number of bits is read from the bottom byte of a register. It can optionally update
2798// the condition flags based on the result.
2799bool
2800EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2801{
2802#if 0
2803 // ARM pseudo code...
2804 if ConditionPassed() then
2805 EncodingSpecificOperations();
2806 shift_n = UInt(R[m]<7:0>);
2807 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2808 R[d] = result;
2809 if setflags then
2810 APSR.N = result<31>;
2811 APSR.Z = IsZeroBit(result);
2812 APSR.C = carry;
2813 // APSR.V unchanged
2814#endif
2815
2816 return EmulateShiftReg(encoding, SRType_ASR);
2817}
2818
2819// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2820// shifting in zeros, and writes the result to the destination register. It can optionally
2821// update the condition flags based on the result.
2822bool
2823EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2824{
2825#if 0
2826 // ARM pseudo code...
2827 if ConditionPassed() then
2828 EncodingSpecificOperations();
2829 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2830 if d == 15 then // Can only occur for ARM encoding
2831 ALUWritePC(result); // setflags is always FALSE here
2832 else
2833 R[d] = result;
2834 if setflags then
2835 APSR.N = result<31>;
2836 APSR.Z = IsZeroBit(result);
2837 APSR.C = carry;
2838 // APSR.V unchanged
2839#endif
2840
2841 return EmulateShiftImm(encoding, SRType_LSL);
2842}
2843
2844// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2845// shifting in zeros, and writes the result to the destination register. The variable number
2846// of bits is read from the bottom byte of a register. It can optionally update the condition
2847// flags based on the result.
2848bool
2849EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2850{
2851#if 0
2852 // ARM pseudo code...
2853 if ConditionPassed() then
2854 EncodingSpecificOperations();
2855 shift_n = UInt(R[m]<7:0>);
2856 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2857 R[d] = result;
2858 if setflags then
2859 APSR.N = result<31>;
2860 APSR.Z = IsZeroBit(result);
2861 APSR.C = carry;
2862 // APSR.V unchanged
2863#endif
2864
2865 return EmulateShiftReg(encoding, SRType_LSL);
2866}
2867
2868// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2869// shifting in zeros, and writes the result to the destination register. It can optionally
2870// update the condition flags based on the result.
2871bool
2872EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2873{
2874#if 0
2875 // ARM pseudo code...
2876 if ConditionPassed() then
2877 EncodingSpecificOperations();
2878 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2879 if d == 15 then // Can only occur for ARM encoding
2880 ALUWritePC(result); // setflags is always FALSE here
2881 else
2882 R[d] = result;
2883 if setflags then
2884 APSR.N = result<31>;
2885 APSR.Z = IsZeroBit(result);
2886 APSR.C = carry;
2887 // APSR.V unchanged
2888#endif
2889
2890 return EmulateShiftImm(encoding, SRType_LSR);
2891}
2892
2893// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2894// shifting in zeros, and writes the result to the destination register. The variable number
2895// of bits is read from the bottom byte of a register. It can optionally update the condition
2896// flags based on the result.
2897bool
2898EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2899{
2900#if 0
2901 // ARM pseudo code...
2902 if ConditionPassed() then
2903 EncodingSpecificOperations();
2904 shift_n = UInt(R[m]<7:0>);
2905 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2906 R[d] = result;
2907 if setflags then
2908 APSR.N = result<31>;
2909 APSR.Z = IsZeroBit(result);
2910 APSR.C = carry;
2911 // APSR.V unchanged
2912#endif
2913
2914 return EmulateShiftReg(encoding, SRType_LSR);
2915}
2916
Johnny Cheneeab4852011-02-16 22:14:44 +00002917// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2918// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2919// It can optionally update the condition flags based on the result.
2920bool
2921EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2922{
2923#if 0
2924 // ARM pseudo code...
2925 if ConditionPassed() then
2926 EncodingSpecificOperations();
2927 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2928 if d == 15 then // Can only occur for ARM encoding
2929 ALUWritePC(result); // setflags is always FALSE here
2930 else
2931 R[d] = result;
2932 if setflags then
2933 APSR.N = result<31>;
2934 APSR.Z = IsZeroBit(result);
2935 APSR.C = carry;
2936 // APSR.V unchanged
2937#endif
2938
2939 return EmulateShiftImm(encoding, SRType_ROR);
2940}
2941
2942// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2943// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2944// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2945// flags based on the result.
2946bool
2947EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2948{
2949#if 0
2950 // ARM pseudo code...
2951 if ConditionPassed() then
2952 EncodingSpecificOperations();
2953 shift_n = UInt(R[m]<7:0>);
2954 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2955 R[d] = result;
2956 if setflags then
2957 APSR.N = result<31>;
2958 APSR.Z = IsZeroBit(result);
2959 APSR.C = carry;
2960 // APSR.V unchanged
2961#endif
2962
2963 return EmulateShiftReg(encoding, SRType_ROR);
2964}
2965
2966// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2967// with the carry flag shifted into bit [31].
2968//
2969// RRX can optionally update the condition flags based on the result.
2970// In that case, bit [0] is shifted into the carry flag.
2971bool
2972EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2973{
2974#if 0
2975 // ARM pseudo code...
2976 if ConditionPassed() then
2977 EncodingSpecificOperations();
2978 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2979 if d == 15 then // Can only occur for ARM encoding
2980 ALUWritePC(result); // setflags is always FALSE here
2981 else
2982 R[d] = result;
2983 if setflags then
2984 APSR.N = result<31>;
2985 APSR.Z = IsZeroBit(result);
2986 APSR.C = carry;
2987 // APSR.V unchanged
2988#endif
2989
2990 return EmulateShiftImm(encoding, SRType_RRX);
2991}
2992
Johnny Chen41a0a152011-02-16 01:27:54 +00002993bool
2994EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2995{
2996 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2997
Johnny Chen82f16aa2011-02-15 20:10:55 +00002998 bool success = false;
2999 const uint32_t opcode = OpcodeAsUnsigned (&success);
3000 if (!success)
3001 return false;
3002
3003 if (ConditionPassed())
3004 {
Johnny Chene7f89532011-02-15 23:22:46 +00003005 uint32_t Rd; // the destination register
3006 uint32_t Rm; // the first operand register
3007 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003008 uint32_t carry; // the carry bit after the shift operation
3009 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003010
3011 // Special case handling!
3012 // A8.6.139 ROR (immediate) -- Encoding T1
3013 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3014 {
3015 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3016 // have the same decoding of bit fields as the other Thumb2 shift operations.
3017 encoding = eEncodingT2;
3018 }
3019
Johnny Chen82f16aa2011-02-15 20:10:55 +00003020 switch (encoding) {
3021 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003022 // Due to the above special case handling!
3023 assert(shift_type != SRType_ROR);
3024
Johnny Chen82f16aa2011-02-15 20:10:55 +00003025 Rd = Bits32(opcode, 2, 0);
3026 Rm = Bits32(opcode, 5, 3);
3027 setflags = !InITBlock();
3028 imm5 = Bits32(opcode, 10, 6);
3029 break;
3030 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003031 // A8.6.141 RRX
3032 assert(shift_type != SRType_RRX);
3033
Johnny Chen82f16aa2011-02-15 20:10:55 +00003034 Rd = Bits32(opcode, 11, 8);
3035 Rm = Bits32(opcode, 3, 0);
3036 setflags = BitIsSet(opcode, 20);
3037 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3038 if (BadReg(Rd) || BadReg(Rm))
3039 return false;
3040 break;
3041 case eEncodingA1:
3042 Rd = Bits32(opcode, 15, 12);
3043 Rm = Bits32(opcode, 3, 0);
3044 setflags = BitIsSet(opcode, 20);
3045 imm5 = Bits32(opcode, 11, 7);
3046 break;
3047 default:
3048 return false;
3049 }
3050
Johnny Cheneeab4852011-02-16 22:14:44 +00003051 // A8.6.139 ROR (immediate)
3052 if (shift_type == SRType_ROR && imm5 == 0)
3053 shift_type = SRType_RRX;
3054
Johnny Chen82f16aa2011-02-15 20:10:55 +00003055 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003056 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003057 if (!success)
3058 return false;
3059
Johnny Cheneeab4852011-02-16 22:14:44 +00003060 // Decode the shift amount if not RRX.
3061 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003062
Johnny Chene97c0d52011-02-18 19:32:20 +00003063 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003064
3065 // The context specifies that an immediate is to be moved into Rd.
3066 EmulateInstruction::Context context;
3067 context.type = EmulateInstruction::eContextImmediate;
3068 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003069
Johnny Chen10530c22011-02-17 22:37:12 +00003070 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003071 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003072 }
3073 return true;
3074}
3075
Johnny Chene7f89532011-02-15 23:22:46 +00003076bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003077EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003078{
Johnny Chen41a0a152011-02-16 01:27:54 +00003079 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003080
3081 bool success = false;
3082 const uint32_t opcode = OpcodeAsUnsigned (&success);
3083 if (!success)
3084 return false;
3085
3086 if (ConditionPassed())
3087 {
3088 uint32_t Rd; // the destination register
3089 uint32_t Rn; // the first operand register
3090 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3091 uint32_t carry; // the carry bit after the shift operation
3092 bool setflags;
3093 switch (encoding) {
3094 case eEncodingT1:
3095 Rd = Bits32(opcode, 2, 0);
3096 Rn = Rd;
3097 Rm = Bits32(opcode, 5, 3);
3098 setflags = !InITBlock();
3099 break;
3100 case eEncodingT2:
3101 Rd = Bits32(opcode, 11, 8);
3102 Rn = Bits32(opcode, 19, 16);
3103 Rm = Bits32(opcode, 3, 0);
3104 setflags = BitIsSet(opcode, 20);
3105 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3106 return false;
3107 break;
3108 case eEncodingA1:
3109 Rd = Bits32(opcode, 15, 12);
3110 Rn = Bits32(opcode, 3, 0);
3111 Rm = Bits32(opcode, 11, 8);
3112 setflags = BitIsSet(opcode, 20);
3113 if (Rd == 15 || Rn == 15 || Rm == 15)
3114 return false;
3115 break;
3116 default:
3117 return false;
3118 }
3119
3120 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003121 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003122 if (!success)
3123 return false;
3124 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003125 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003126 if (!success)
3127 return false;
3128
3129 // Get the shift amount.
3130 uint32_t amt = Bits32(val, 7, 0);
3131
Johnny Chene97c0d52011-02-18 19:32:20 +00003132 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003133
3134 // The context specifies that an immediate is to be moved into Rd.
3135 EmulateInstruction::Context context;
3136 context.type = EmulateInstruction::eContextImmediate;
3137 context.SetNoArgs ();
3138
Johnny Chen10530c22011-02-17 22:37:12 +00003139 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003140 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003141 }
3142 return true;
3143}
3144
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003145// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003146// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003147// can be written back to the base register.
3148bool
3149EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3150{
3151#if 0
3152 // ARM pseudo code...
3153 if ConditionPassed()
3154 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3155 address = R[n];
3156
3157 for i = 0 to 14
3158 if registers<i> == '1' then
3159 R[i] = MemA[address, 4]; address = address + 4;
3160 if registers<15> == '1' then
3161 LoadWritePC (MemA[address, 4]);
3162
3163 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3164 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3165
3166#endif
3167
3168 bool success = false;
3169 const uint32_t opcode = OpcodeAsUnsigned (&success);
3170 if (!success)
3171 return false;
3172
3173 if (ConditionPassed())
3174 {
3175 uint32_t n;
3176 uint32_t registers = 0;
3177 bool wback;
3178 const uint32_t addr_byte_size = GetAddressByteSize();
3179 switch (encoding)
3180 {
3181 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003182 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003183 n = Bits32 (opcode, 10, 8);
3184 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003185 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003186 wback = BitIsClear (registers, n);
3187 // if BitCount(registers) < 1 then UNPREDICTABLE;
3188 if (BitCount(registers) < 1)
3189 return false;
3190 break;
3191 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003192 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3193 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003194 n = Bits32 (opcode, 19, 16);
3195 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003196 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003197 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003198
3199 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003200 if ((n == 15)
3201 || (BitCount (registers) < 2)
3202 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3203 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003204
3205 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003206 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003207 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003208
3209 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003210 if (wback
3211 && BitIsSet (registers, n))
3212 return false;
3213 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003214
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003215 case eEncodingA1:
3216 n = Bits32 (opcode, 19, 16);
3217 registers = Bits32 (opcode, 15, 0);
3218 wback = BitIsSet (opcode, 21);
3219 if ((n == 15)
3220 || (BitCount (registers) < 1))
3221 return false;
3222 break;
3223 default:
3224 return false;
3225 }
3226
3227 int32_t offset = 0;
3228 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3229 if (!success)
3230 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003231
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003232 EmulateInstruction::Context context;
3233 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3234 Register dwarf_reg;
3235 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3236 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003237
3238 for (int i = 0; i < 14; ++i)
3239 {
3240 if (BitIsSet (registers, i))
3241 {
Caroline Tice85aab332011-02-08 23:56:10 +00003242 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003243 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244 if (wback && (n == 13)) // Pop Instruction
3245 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3246
3247 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003248 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003249 if (!success)
3250 return false;
3251
3252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3253 return false;
3254
3255 offset += addr_byte_size;
3256 }
3257 }
3258
3259 if (BitIsSet (registers, 15))
3260 {
3261 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003262 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003263 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003264 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003265 if (!success)
3266 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003267 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003268 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269 return false;
3270 }
3271
3272 if (wback && BitIsClear (registers, n))
3273 {
Caroline Ticefa172202011-02-11 22:49:54 +00003274 // R[n] = R[n] + 4 * BitCount (registers)
3275 int32_t offset = addr_byte_size * BitCount (registers);
3276 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003277 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003278
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3280 return false;
3281 }
3282 if (wback && BitIsSet (registers, n))
3283 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003284 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003285 }
3286 return true;
3287}
Caroline Tice713c2662011-02-11 17:59:55 +00003288
3289// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3290// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3291// can optionally be written back tot he base registers.
3292bool
3293EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3294{
3295#if 0
3296 // ARM pseudo code...
3297 if ConditionPassed() then
3298 EncodingSpecificOperations();
3299 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003300
Caroline Tice713c2662011-02-11 17:59:55 +00003301 for i = 0 to 14
3302 if registers<i> == ’1’ then
3303 R[i] = MemA[address,4]; address = address + 4;
3304
3305 if registers<15> == ’1’ then
3306 LoadWritePC(MemA[address,4]);
3307
3308 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3309 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3310#endif
3311
3312 bool success = false;
3313 const uint32_t opcode = OpcodeAsUnsigned (&success);
3314 if (!success)
3315 return false;
3316
3317 if (ConditionPassed())
3318 {
3319 uint32_t n;
3320 uint32_t registers = 0;
3321 bool wback;
3322 const uint32_t addr_byte_size = GetAddressByteSize();
3323
3324 // EncodingSpecificOperations();
3325 switch (encoding)
3326 {
3327 case eEncodingA1:
3328 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3329 n = Bits32 (opcode, 19, 16);
3330 registers = Bits32 (opcode, 15, 0);
3331 wback = BitIsSet (opcode, 21);
3332
3333 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3334 if ((n == 15) || (BitCount (registers) < 1))
3335 return false;
3336
3337 break;
3338
3339 default:
3340 return false;
3341 }
3342 // address = R[n] - 4*BitCount(registers) + 4;
3343
3344 int32_t offset = 0;
3345 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3346
3347 if (!success)
3348 return false;
3349
3350 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3351
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003352 EmulateInstruction::Context context;
3353 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3354 Register dwarf_reg;
3355 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3356 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003357
3358 // for i = 0 to 14
3359 for (int i = 0; i < 14; ++i)
3360 {
3361 // if registers<i> == ’1’ then
3362 if (BitIsSet (registers, i))
3363 {
3364 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003365 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003366 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003367 if (!success)
3368 return false;
3369 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3370 return false;
3371 offset += addr_byte_size;
3372 }
3373 }
3374
3375 // if registers<15> == ’1’ then
3376 // LoadWritePC(MemA[address,4]);
3377 if (BitIsSet (registers, 15))
3378 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003379 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003380 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003381 if (!success)
3382 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003383 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003384 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003385 return false;
3386 }
3387
3388 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3389 if (wback && BitIsClear (registers, n))
3390 {
Caroline Tice713c2662011-02-11 17:59:55 +00003391 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3392 if (!success)
3393 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003394
3395 offset = (addr_byte_size * BitCount (registers)) * -1;
3396 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003397 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003398 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003399 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3400 return false;
3401 }
3402
3403 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3404 if (wback && BitIsSet (registers, n))
3405 return WriteBits32Unknown (n);
3406 }
3407 return true;
3408}
3409
3410// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3411// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3412// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003413bool
3414EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3415{
3416#if 0
3417 // ARM pseudo code...
3418 if ConditionPassed() then
3419 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3420 address = R[n] - 4*BitCount(registers);
3421
3422 for i = 0 to 14
3423 if registers<i> == ’1’ then
3424 R[i] = MemA[address,4]; address = address + 4;
3425 if registers<15> == ’1’ then
3426 LoadWritePC(MemA[address,4]);
3427
3428 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3429 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3430#endif
3431
3432 bool success = false;
3433 const uint32_t opcode = OpcodeAsUnsigned (&success);
3434 if (!success)
3435 return false;
3436
3437 if (ConditionPassed())
3438 {
3439 uint32_t n;
3440 uint32_t registers = 0;
3441 bool wback;
3442 const uint32_t addr_byte_size = GetAddressByteSize();
3443 switch (encoding)
3444 {
3445 case eEncodingT1:
3446 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3447 n = Bits32 (opcode, 19, 16);
3448 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003449 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003450 wback = BitIsSet (opcode, 21);
3451
3452 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3453 if ((n == 15)
3454 || (BitCount (registers) < 2)
3455 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3456 return false;
3457
3458 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003459 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003460 return false;
3461
3462 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3463 if (wback && BitIsSet (registers, n))
3464 return false;
3465
3466 break;
3467
3468 case eEncodingA1:
3469 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3470 n = Bits32 (opcode, 19, 16);
3471 registers = Bits32 (opcode, 15, 0);
3472 wback = BitIsSet (opcode, 21);
3473
3474 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3475 if ((n == 15) || (BitCount (registers) < 1))
3476 return false;
3477
3478 break;
3479
3480 default:
3481 return false;
3482 }
3483
Caroline Tice713c2662011-02-11 17:59:55 +00003484 // address = R[n] - 4*BitCount(registers);
3485
Caroline Tice0b29e242011-02-08 23:16:02 +00003486 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003487 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3488
3489 if (!success)
3490 return false;
3491
3492 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003493 EmulateInstruction::Context context;
3494 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3495 Register dwarf_reg;
3496 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3497 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003498
3499 for (int i = 0; i < 14; ++i)
3500 {
3501 if (BitIsSet (registers, i))
3502 {
3503 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003504 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003505 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003506 if (!success)
3507 return false;
3508
3509 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3510 return false;
3511
3512 offset += addr_byte_size;
3513 }
3514 }
3515
3516 // if registers<15> == ’1’ then
3517 // LoadWritePC(MemA[address,4]);
3518 if (BitIsSet (registers, 15))
3519 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003520 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003521 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003522 if (!success)
3523 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003524 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003525 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003526 return false;
3527 }
3528
3529 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3530 if (wback && BitIsClear (registers, n))
3531 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003532 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3533 if (!success)
3534 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003535
3536 offset = (addr_byte_size * BitCount (registers)) * -1;
3537 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003538 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003539 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003540 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3541 return false;
3542 }
3543
3544 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3545 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003546 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003547 }
3548 return true;
3549}
Caroline Tice85aab332011-02-08 23:56:10 +00003550
Caroline Tice713c2662011-02-11 17:59:55 +00003551// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3552// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3553// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003554bool
3555EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3556{
3557#if 0
3558 if ConditionPassed() then
3559 EncodingSpecificOperations();
3560 address = R[n] + 4;
3561
3562 for i = 0 to 14
3563 if registers<i> == ’1’ then
3564 R[i] = MemA[address,4]; address = address + 4;
3565 if registers<15> == ’1’ then
3566 LoadWritePC(MemA[address,4]);
3567
3568 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3569 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3570#endif
3571
3572 bool success = false;
3573 const uint32_t opcode = OpcodeAsUnsigned (&success);
3574 if (!success)
3575 return false;
3576
3577 if (ConditionPassed())
3578 {
3579 uint32_t n;
3580 uint32_t registers = 0;
3581 bool wback;
3582 const uint32_t addr_byte_size = GetAddressByteSize();
3583 switch (encoding)
3584 {
3585 case eEncodingA1:
3586 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3587 n = Bits32 (opcode, 19, 16);
3588 registers = Bits32 (opcode, 15, 0);
3589 wback = BitIsSet (opcode, 21);
3590
3591 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3592 if ((n == 15) || (BitCount (registers) < 1))
3593 return false;
3594
3595 break;
3596 default:
3597 return false;
3598 }
3599 // address = R[n] + 4;
3600
3601 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003602 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3603
3604 if (!success)
3605 return false;
3606
3607 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003608
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003609 EmulateInstruction::Context context;
3610 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3611 Register dwarf_reg;
3612 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3613 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003614
3615 for (int i = 0; i < 14; ++i)
3616 {
3617 if (BitIsSet (registers, i))
3618 {
3619 // R[i] = MemA[address,4]; address = address + 4;
3620
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003621 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003622 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003623 if (!success)
3624 return false;
3625
3626 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3627 return false;
3628
3629 offset += addr_byte_size;
3630 }
3631 }
3632
3633 // if registers<15> == ’1’ then
3634 // LoadWritePC(MemA[address,4]);
3635 if (BitIsSet (registers, 15))
3636 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003637 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003638 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003639 if (!success)
3640 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003641 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003642 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003643 return false;
3644 }
3645
3646 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3647 if (wback && BitIsClear (registers, n))
3648 {
Caroline Tice85aab332011-02-08 23:56:10 +00003649 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3650 if (!success)
3651 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003652
3653 offset = addr_byte_size * BitCount (registers);
3654 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003655 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003656 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003657 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3658 return false;
3659 }
3660
3661 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3662 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003663 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003664 }
3665 return true;
3666}
Caroline Tice0b29e242011-02-08 23:16:02 +00003667
Johnny Chenef21b592011-02-10 01:52:38 +00003668// Load Register (immediate) calculates an address from a base register value and
3669// an immediate offset, loads a word from memory, and writes to a register.
3670// LDR (immediate, Thumb)
3671bool
3672EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3673{
3674#if 0
3675 // ARM pseudo code...
3676 if (ConditionPassed())
3677 {
3678 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3679 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3680 address = if index then offset_addr else R[n];
3681 data = MemU[address,4];
3682 if wback then R[n] = offset_addr;
3683 if t == 15 then
3684 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3685 elsif UnalignedSupport() || address<1:0> = '00' then
3686 R[t] = data;
3687 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3688 }
3689#endif
3690
3691 bool success = false;
3692 const uint32_t opcode = OpcodeAsUnsigned (&success);
3693 if (!success)
3694 return false;
3695
3696 if (ConditionPassed())
3697 {
3698 uint32_t Rt; // the destination register
3699 uint32_t Rn; // the base register
3700 uint32_t imm32; // the immediate offset used to form the address
3701 addr_t offset_addr; // the offset address
3702 addr_t address; // the calculated address
3703 uint32_t data; // the literal data value from memory load
3704 bool add, index, wback;
3705 switch (encoding) {
3706 case eEncodingT1:
3707 Rt = Bits32(opcode, 5, 3);
3708 Rn = Bits32(opcode, 2, 0);
3709 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3710 // index = TRUE; add = TRUE; wback = FALSE
3711 add = true;
3712 index = true;
3713 wback = false;
3714 break;
3715 default:
3716 return false;
3717 }
3718 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3719 if (!success)
3720 return false;
3721 if (add)
3722 offset_addr = base + imm32;
3723 else
3724 offset_addr = base - imm32;
3725
3726 address = (index ? offset_addr : base);
3727
3728 if (wback)
3729 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003730 EmulateInstruction::Context ctx;
3731 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3732 Register dwarf_reg;
3733 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3734 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3735
Johnny Chenef21b592011-02-10 01:52:38 +00003736 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3737 return false;
3738 }
3739
3740 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003741 EmulateInstruction::Context context;
3742 context.type = EmulateInstruction::eContextImmediate;
3743 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003744
3745 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003746 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003747 if (!success)
3748 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003749
3750 if (Rt == 15)
3751 {
3752 if (Bits32(address, 1, 0) == 0)
3753 {
Johnny Chen668b4512011-02-15 21:08:58 +00003754 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003755 return false;
3756 }
3757 else
3758 return false;
3759 }
3760 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3761 {
3762 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3763 return false;
3764 }
3765 else
3766 return false;
3767 }
3768 return true;
3769}
3770
Caroline Ticeaf556562011-02-15 18:42:15 +00003771// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3772// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3773// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003774bool
3775EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3776{
3777#if 0
3778 if ConditionPassed() then
3779 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3780 address = R[n];
3781
3782 for i = 0 to 14
3783 if registers<i> == ’1’ then
3784 if i == n && wback && i != LowestSetBit(registers) then
3785 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3786 else
3787 MemA[address,4] = R[i];
3788 address = address + 4;
3789
3790 if registers<15> == ’1’ then // Only possible for encoding A1
3791 MemA[address,4] = PCStoreValue();
3792 if wback then R[n] = R[n] + 4*BitCount(registers);
3793#endif
3794
3795 bool success = false;
3796 const uint32_t opcode = OpcodeAsUnsigned (&success);
3797 if (!success)
3798 return false;
3799
3800 if (ConditionPassed ())
3801 {
3802 uint32_t n;
3803 uint32_t registers = 0;
3804 bool wback;
3805 const uint32_t addr_byte_size = GetAddressByteSize();
3806
3807 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3808 switch (encoding)
3809 {
3810 case eEncodingT1:
3811 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3812 n = Bits32 (opcode, 10, 8);
3813 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003814 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003815 wback = true;
3816
3817 // if BitCount(registers) < 1 then UNPREDICTABLE;
3818 if (BitCount (registers) < 1)
3819 return false;
3820
3821 break;
3822
3823 case eEncodingT2:
3824 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3825 n = Bits32 (opcode, 19, 16);
3826 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003827 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003828 wback = BitIsSet (opcode, 21);
3829
3830 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3831 if ((n == 15) || (BitCount (registers) < 2))
3832 return false;
3833
3834 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3835 if (wback && BitIsSet (registers, n))
3836 return false;
3837
3838 break;
3839
3840 case eEncodingA1:
3841 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3842 n = Bits32 (opcode, 19, 16);
3843 registers = Bits32 (opcode, 15, 0);
3844 wback = BitIsSet (opcode, 21);
3845
3846 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3847 if ((n == 15) || (BitCount (registers) < 1))
3848 return false;
3849
3850 break;
3851
3852 default:
3853 return false;
3854 }
3855
3856 // address = R[n];
3857 int32_t offset = 0;
3858 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3859 if (!success)
3860 return false;
3861
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003862 EmulateInstruction::Context context;
3863 context.type = EmulateInstruction::eContextRegisterStore;
3864 Register base_reg;
3865 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003866
3867 // for i = 0 to 14
3868 for (int i = 0; i < 14; ++i)
3869 {
3870 int lowest_set_bit = 14;
3871 // if registers<i> == ’1’ then
3872 if (BitIsSet (registers, i))
3873 {
3874 if (i < lowest_set_bit)
3875 lowest_set_bit = i;
3876 // if i == n && wback && i != LowestSetBit(registers) then
3877 if ((i == n) && wback && (i != lowest_set_bit))
3878 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3879 WriteBits32UnknownToMemory (address + offset);
3880 else
3881 {
3882 // MemA[address,4] = R[i];
3883 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3884 if (!success)
3885 return false;
3886
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003887 Register data_reg;
3888 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3889 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003890 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003891 return false;
3892 }
3893
3894 // address = address + 4;
3895 offset += addr_byte_size;
3896 }
3897 }
3898
3899 // if registers<15> == ’1’ then // Only possible for encoding A1
3900 // MemA[address,4] = PCStoreValue();
3901 if (BitIsSet (registers, 15))
3902 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003903 Register pc_reg;
3904 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3905 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003906 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3907 if (!success)
3908 return false;
3909
Caroline Ticecc96eb52011-02-17 19:20:40 +00003910 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003911 return false;
3912 }
3913
3914 // if wback then R[n] = R[n] + 4*BitCount(registers);
3915 if (wback)
3916 {
3917 offset = addr_byte_size * BitCount (registers);
3918 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003919 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003920 addr_t data = address + offset;
3921 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3922 return false;
3923 }
3924 }
3925 return true;
3926}
3927
Caroline Ticeaf556562011-02-15 18:42:15 +00003928// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3929// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3930// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003931bool
3932EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3933{
3934#if 0
3935 if ConditionPassed() then
3936 EncodingSpecificOperations();
3937 address = R[n] - 4*BitCount(registers) + 4;
3938
3939 for i = 0 to 14
3940 if registers<i> == ’1’ then
3941 if i == n && wback && i != LowestSetBit(registers) then
3942 MemA[address,4] = bits(32) UNKNOWN;
3943 else
3944 MemA[address,4] = R[i];
3945 address = address + 4;
3946
3947 if registers<15> == ’1’ then
3948 MemA[address,4] = PCStoreValue();
3949
3950 if wback then R[n] = R[n] - 4*BitCount(registers);
3951#endif
3952
3953 bool success = false;
3954 const uint32_t opcode = OpcodeAsUnsigned (&success);
3955 if (!success)
3956 return false;
3957
3958 if (ConditionPassed ())
3959 {
3960 uint32_t n;
3961 uint32_t registers = 0;
3962 bool wback;
3963 const uint32_t addr_byte_size = GetAddressByteSize();
3964
3965 // EncodingSpecificOperations();
3966 switch (encoding)
3967 {
3968 case eEncodingA1:
3969 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3970 n = Bits32 (opcode, 19, 16);
3971 registers = Bits32 (opcode, 15, 0);
3972 wback = BitIsSet (opcode, 21);
3973
3974 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3975 if ((n == 15) || (BitCount (registers) < 1))
3976 return false;
3977 break;
3978 default:
3979 return false;
3980 }
3981
3982 // address = R[n] - 4*BitCount(registers) + 4;
3983 int32_t offset = 0;
3984 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3985 if (!success)
3986 return false;
3987
3988 address = address - (addr_byte_size * BitCount (registers)) + 4;
3989
3990 EmulateInstruction::Context context;
3991 context.type = EmulateInstruction::eContextRegisterStore;
3992 Register base_reg;
3993 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3994
3995 // for i = 0 to 14
3996 for (int i = 0; i < 14; ++i)
3997 {
3998 int lowest_bit_set = 14;
3999 // if registers<i> == ’1’ then
4000 if (BitIsSet (registers, i))
4001 {
4002 if (i < lowest_bit_set)
4003 lowest_bit_set = i;
4004 //if i == n && wback && i != LowestSetBit(registers) then
4005 if ((i == n) && wback && (i != lowest_bit_set))
4006 // MemA[address,4] = bits(32) UNKNOWN;
4007 WriteBits32UnknownToMemory (address + offset);
4008 else
4009 {
4010 // MemA[address,4] = R[i];
4011 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4012 if (!success)
4013 return false;
4014
4015 Register data_reg;
4016 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4017 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004018 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004019 return false;
4020 }
4021
4022 // address = address + 4;
4023 offset += addr_byte_size;
4024 }
4025 }
4026
4027 // if registers<15> == ’1’ then
4028 // MemA[address,4] = PCStoreValue();
4029 if (BitIsSet (registers, 15))
4030 {
4031 Register pc_reg;
4032 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4033 context.SetRegisterPlusOffset (pc_reg, 8);
4034 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4035 if (!success)
4036 return false;
4037
Caroline Ticecc96eb52011-02-17 19:20:40 +00004038 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004039 return false;
4040 }
4041
4042 // if wback then R[n] = R[n] - 4*BitCount(registers);
4043 if (wback)
4044 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004045 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004046 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4047 context.SetImmediateSigned (offset);
4048 addr_t data = address + offset;
4049 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4050 return false;
4051 }
4052 }
4053 return true;
4054}
4055
Caroline Ticeaf556562011-02-15 18:42:15 +00004056// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4057// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4058// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004059bool
4060EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4061{
4062#if 0
4063 if ConditionPassed() then
4064 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4065 address = R[n] - 4*BitCount(registers);
4066
4067 for i = 0 to 14
4068 if registers<i> == ’1’ then
4069 if i == n && wback && i != LowestSetBit(registers) then
4070 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4071 else
4072 MemA[address,4] = R[i];
4073 address = address + 4;
4074
4075 if registers<15> == ’1’ then // Only possible for encoding A1
4076 MemA[address,4] = PCStoreValue();
4077
4078 if wback then R[n] = R[n] - 4*BitCount(registers);
4079#endif
4080
4081
4082 bool success = false;
4083 const uint32_t opcode = OpcodeAsUnsigned (&success);
4084 if (!success)
4085 return false;
4086
4087 if (ConditionPassed ())
4088 {
4089 uint32_t n;
4090 uint32_t registers = 0;
4091 bool wback;
4092 const uint32_t addr_byte_size = GetAddressByteSize();
4093
4094 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4095 switch (encoding)
4096 {
4097 case eEncodingT1:
4098 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4099 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4100 {
4101 // See PUSH
4102 }
4103 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4104 n = Bits32 (opcode, 19, 16);
4105 registers = Bits32 (opcode, 15, 0);
4106 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4107 wback = BitIsSet (opcode, 21);
4108 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4109 if ((n == 15) || BitCount (registers) < 2)
4110 return false;
4111 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4112 if (wback && BitIsSet (registers, n))
4113 return false;
4114 break;
4115
4116 case eEncodingA1:
4117 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4118 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4119 {
4120 // See Push
4121 }
4122 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4123 n = Bits32 (opcode, 19, 16);
4124 registers = Bits32 (opcode, 15, 0);
4125 wback = BitIsSet (opcode, 21);
4126 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4127 if ((n == 15) || BitCount (registers) < 1)
4128 return false;
4129 break;
4130
4131 default:
4132 return false;
4133 }
4134
4135 // address = R[n] - 4*BitCount(registers);
4136
4137 int32_t offset = 0;
4138 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4139 if (!success)
4140 return false;
4141
4142 address = address - (addr_byte_size * BitCount (registers));
4143
4144 EmulateInstruction::Context context;
4145 context.type = EmulateInstruction::eContextRegisterStore;
4146 Register base_reg;
4147 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4148
4149 // for i = 0 to 14
4150 for (int i = 0; i < 14; ++i)
4151 {
4152 uint32_t lowest_set_bit = 14;
4153 // if registers<i> == ’1’ then
4154 if (BitIsSet (registers, i))
4155 {
4156 if (i < lowest_set_bit)
4157 lowest_set_bit = i;
4158 // if i == n && wback && i != LowestSetBit(registers) then
4159 if ((i == n) && wback && (i != lowest_set_bit))
4160 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4161 WriteBits32UnknownToMemory (address + offset);
4162 else
4163 {
4164 // MemA[address,4] = R[i];
4165 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4166 if (!success)
4167 return false;
4168
4169 Register data_reg;
4170 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4171 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004172 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004173 return false;
4174 }
4175
4176 // address = address + 4;
4177 offset += addr_byte_size;
4178 }
4179 }
4180
4181 // if registers<15> == ’1’ then // Only possible for encoding A1
4182 // MemA[address,4] = PCStoreValue();
4183 if (BitIsSet (registers, 15))
4184 {
4185 Register pc_reg;
4186 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4187 context.SetRegisterPlusOffset (pc_reg, 8);
4188 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4189 if (!success)
4190 return false;
4191
Caroline Ticecc96eb52011-02-17 19:20:40 +00004192 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004193 return false;
4194 }
4195
4196 // if wback then R[n] = R[n] - 4*BitCount(registers);
4197 if (wback)
4198 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004199 offset = (addr_byte_size * BitCount (registers)) * -1;
4200 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4201 context.SetImmediateSigned (offset);
4202 addr_t data = address + offset;
4203 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4204 return false;
4205 }
4206 }
4207 return true;
4208}
4209
4210// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4211// from a base register. The consecutive memory locations start just above this address, and the address of the last
4212// of those locations can optionally be written back to the base register.
4213bool
4214EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4215{
4216#if 0
4217 if ConditionPassed() then
4218 EncodingSpecificOperations();
4219 address = R[n] + 4;
4220
4221 for i = 0 to 14
4222 if registers<i> == ’1’ then
4223 if i == n && wback && i != LowestSetBit(registers) then
4224 MemA[address,4] = bits(32) UNKNOWN;
4225 else
4226 MemA[address,4] = R[i];
4227 address = address + 4;
4228
4229 if registers<15> == ’1’ then
4230 MemA[address,4] = PCStoreValue();
4231
4232 if wback then R[n] = R[n] + 4*BitCount(registers);
4233#endif
4234
4235 bool success = false;
4236 const uint32_t opcode = OpcodeAsUnsigned (&success);
4237 if (!success)
4238 return false;
4239
4240 if (ConditionPassed())
4241 {
4242 uint32_t n;
4243 uint32_t registers = 0;
4244 bool wback;
4245 const uint32_t addr_byte_size = GetAddressByteSize();
4246
4247 // EncodingSpecificOperations();
4248 switch (encoding)
4249 {
4250 case eEncodingA1:
4251 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4252 n = Bits32 (opcode, 19, 16);
4253 registers = Bits32 (opcode, 15, 0);
4254 wback = BitIsSet (opcode, 21);
4255
4256 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4257 if ((n == 15) && (BitCount (registers) < 1))
4258 return false;
4259 break;
4260 default:
4261 return false;
4262 }
4263 // address = R[n] + 4;
4264
4265 int32_t offset = 0;
4266 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4267 if (!success)
4268 return false;
4269
4270 address = address + addr_byte_size;
4271
4272 EmulateInstruction::Context context;
4273 context.type = EmulateInstruction::eContextRegisterStore;
4274 Register base_reg;
4275 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4276
4277 uint32_t lowest_set_bit = 14;
4278 // for i = 0 to 14
4279 for (int i = 0; i < 14; ++i)
4280 {
4281 // if registers<i> == ’1’ then
4282 if (BitIsSet (registers, i))
4283 {
4284 if (i < lowest_set_bit)
4285 lowest_set_bit = i;
4286 // if i == n && wback && i != LowestSetBit(registers) then
4287 if ((i == n) && wback && (i != lowest_set_bit))
4288 // MemA[address,4] = bits(32) UNKNOWN;
4289 WriteBits32UnknownToMemory (address + offset);
4290 // else
4291 else
4292 {
4293 // MemA[address,4] = R[i];
4294 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4295 if (!success)
4296 return false;
4297
4298 Register data_reg;
4299 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4300 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004301 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004302 return false;
4303 }
4304
4305 // address = address + 4;
4306 offset += addr_byte_size;
4307 }
4308 }
4309
4310 // if registers<15> == ’1’ then
4311 // MemA[address,4] = PCStoreValue();
4312 if (BitIsSet (registers, 15))
4313 {
4314 Register pc_reg;
4315 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4316 context.SetRegisterPlusOffset (pc_reg, 8);
4317 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4318 if (!success)
4319 return false;
4320
Caroline Ticecc96eb52011-02-17 19:20:40 +00004321 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004322 return false;
4323 }
4324
4325 // if wback then R[n] = R[n] + 4*BitCount(registers);
4326 if (wback)
4327 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004328 offset = addr_byte_size * BitCount (registers);
4329 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4330 context.SetImmediateSigned (offset);
4331 addr_t data = address + offset;
4332 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4333 return false;
4334 }
4335 }
4336 return true;
4337}
Caroline Tice7fac8572011-02-15 22:53:54 +00004338
4339// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4340// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4341bool
4342EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4343{
4344#if 0
4345 if ConditionPassed() then
4346 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4347 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4348 address = if index then offset_addr else R[n];
4349 if UnalignedSupport() || address<1:0> == ’00’ then
4350 MemU[address,4] = R[t];
4351 else // Can only occur before ARMv7
4352 MemU[address,4] = bits(32) UNKNOWN;
4353 if wback then R[n] = offset_addr;
4354#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004355
Caroline Tice7fac8572011-02-15 22:53:54 +00004356 bool success = false;
4357 const uint32_t opcode = OpcodeAsUnsigned (&success);
4358 if (!success)
4359 return false;
4360
4361 if (ConditionPassed())
4362 {
4363 const uint32_t addr_byte_size = GetAddressByteSize();
4364
4365 uint32_t t;
4366 uint32_t n;
4367 uint32_t imm32;
4368 bool index;
4369 bool add;
4370 bool wback;
4371 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4372 switch (encoding)
4373 {
4374 case eEncodingT1:
4375 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4376 t = Bits32 (opcode, 2, 0);
4377 n = Bits32 (opcode, 5, 3);
4378 imm32 = Bits32 (opcode, 10, 6) << 2;
4379
4380 // index = TRUE; add = TRUE; wback = FALSE;
4381 index = true;
4382 add = false;
4383 wback = false;
4384 break;
4385
4386 case eEncodingT2:
4387 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4388 t = Bits32 (opcode, 10, 8);
4389 n = 13;
4390 imm32 = Bits32 (opcode, 7, 0) << 2;
4391
4392 // index = TRUE; add = TRUE; wback = FALSE;
4393 index = true;
4394 add = true;
4395 wback = false;
4396 break;
4397
4398 case eEncodingT3:
4399 // if Rn == ’1111’ then UNDEFINED;
4400 if (Bits32 (opcode, 19, 16) == 15)
4401 return false;
4402
4403 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4404 t = Bits32 (opcode, 15, 12);
4405 n = Bits32 (opcode, 19, 16);
4406 imm32 = Bits32 (opcode, 11, 0);
4407
4408 // index = TRUE; add = TRUE; wback = FALSE;
4409 index = true;
4410 add = true;
4411 wback = false;
4412
4413 // if t == 15 then UNPREDICTABLE;
4414 if (t == 15)
4415 return false;
4416 break;
4417
4418 case eEncodingT4:
4419 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4420 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4421 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4422 if ((Bits32 (opcode, 19, 16) == 15)
4423 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4424 return false;
4425
4426 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4427 t = Bits32 (opcode, 15, 12);
4428 n = Bits32 (opcode, 19, 16);
4429 imm32 = Bits32 (opcode, 7, 0);
4430
4431 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4432 index = BitIsSet (opcode, 10);
4433 add = BitIsSet (opcode, 9);
4434 wback = BitIsSet (opcode, 8);
4435
4436 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4437 if ((t == 15) || (wback && (n == t)))
4438 return false;
4439 break;
4440
4441 default:
4442 return false;
4443 }
4444
4445 addr_t offset_addr;
4446 addr_t address;
4447
4448 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4449 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4450 if (!success)
4451 return false;
4452
4453 if (add)
4454 offset_addr = base_address + imm32;
4455 else
4456 offset_addr = base_address - imm32;
4457
4458 // address = if index then offset_addr else R[n];
4459 if (index)
4460 address = offset_addr;
4461 else
4462 address = base_address;
4463
4464 EmulateInstruction::Context context;
4465 context.type = eContextRegisterStore;
4466 Register base_reg;
4467 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4468
4469 // if UnalignedSupport() || address<1:0> == ’00’ then
4470 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4471 {
4472 // MemU[address,4] = R[t];
4473 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4474 if (!success)
4475 return false;
4476
4477 Register data_reg;
4478 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4479 int32_t offset = address - base_address;
4480 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004481 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004482 return false;
4483 }
4484 else
4485 {
4486 // MemU[address,4] = bits(32) UNKNOWN;
4487 WriteBits32UnknownToMemory (address);
4488 }
4489
4490 // if wback then R[n] = offset_addr;
4491 if (wback)
4492 {
4493 context.type = eContextRegisterLoad;
4494 context.SetAddress (offset_addr);
4495 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4496 return false;
4497 }
4498 }
4499 return true;
4500}
Caroline Ticeaf556562011-02-15 18:42:15 +00004501
Caroline Tice3fd63e92011-02-16 00:33:43 +00004502// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4503// word from a register to memory. The offset register value can optionally be shifted.
4504bool
4505EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4506{
4507#if 0
4508 if ConditionPassed() then
4509 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4510 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4511 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4512 address = if index then offset_addr else R[n];
4513 if t == 15 then // Only possible for encoding A1
4514 data = PCStoreValue();
4515 else
4516 data = R[t];
4517 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4518 MemU[address,4] = data;
4519 else // Can only occur before ARMv7
4520 MemU[address,4] = bits(32) UNKNOWN;
4521 if wback then R[n] = offset_addr;
4522#endif
4523
4524 bool success = false;
4525 const uint32_t opcode = OpcodeAsUnsigned (&success);
4526 if (!success)
4527 return false;
4528
4529 if (ConditionPassed())
4530 {
4531 const uint32_t addr_byte_size = GetAddressByteSize();
4532
4533 uint32_t t;
4534 uint32_t n;
4535 uint32_t m;
4536 ARM_ShifterType shift_t;
4537 uint32_t shift_n;
4538 bool index;
4539 bool add;
4540 bool wback;
4541
4542 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4543 switch (encoding)
4544 {
4545 case eEncodingT1:
4546 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4547 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4548 t = Bits32 (opcode, 2, 0);
4549 n = Bits32 (opcode, 5, 3);
4550 m = Bits32 (opcode, 8, 6);
4551
4552 // index = TRUE; add = TRUE; wback = FALSE;
4553 index = true;
4554 add = true;
4555 wback = false;
4556
4557 // (shift_t, shift_n) = (SRType_LSL, 0);
4558 shift_t = SRType_LSL;
4559 shift_n = 0;
4560 break;
4561
4562 case eEncodingT2:
4563 // if Rn == ’1111’ then UNDEFINED;
4564 if (Bits32 (opcode, 19, 16) == 15)
4565 return false;
4566
4567 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4568 t = Bits32 (opcode, 15, 12);
4569 n = Bits32 (opcode, 19, 16);
4570 m = Bits32 (opcode, 3, 0);
4571
4572 // index = TRUE; add = TRUE; wback = FALSE;
4573 index = true;
4574 add = true;
4575 wback = false;
4576
4577 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4578 shift_t = SRType_LSL;
4579 shift_n = Bits32 (opcode, 5, 4);
4580
4581 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4582 if ((t == 15) || (BadReg (m)))
4583 return false;
4584 break;
4585
4586 case eEncodingA1:
4587 {
4588 // if P == ’0’ && W == ’1’ then SEE STRT;
4589 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4590 t = Bits32 (opcode, 15, 12);
4591 n = Bits32 (opcode, 19, 16);
4592 m = Bits32 (opcode, 3, 0);
4593
4594 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4595 index = BitIsSet (opcode, 24);
4596 add = BitIsSet (opcode, 23);
4597 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4598
4599 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4600 uint32_t typ = Bits32 (opcode, 6, 5);
4601 uint32_t imm5 = Bits32 (opcode, 11, 7);
4602 shift_n = DecodeImmShift(typ, imm5, shift_t);
4603
4604 // if m == 15 then UNPREDICTABLE;
4605 if (m == 15)
4606 return false;
4607
4608 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4609 if (wback && ((n == 15) || (n == t)))
4610 return false;
4611
4612 break;
4613 }
4614 default:
4615 return false;
4616 }
4617
4618 addr_t offset_addr;
4619 addr_t address;
4620 int32_t offset = 0;
4621
4622 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4623 if (!success)
4624 return false;
4625
4626 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4627 if (!success)
4628 return false;
4629
4630 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004631 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004632
4633 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4634 if (add)
4635 offset_addr = base_address + offset;
4636 else
4637 offset_addr = base_address - offset;
4638
4639 // address = if index then offset_addr else R[n];
4640 if (index)
4641 address = offset_addr;
4642 else
4643 address = base_address;
4644
4645 uint32_t data;
4646 // if t == 15 then // Only possible for encoding A1
4647 if (t == 15)
4648 // data = PCStoreValue();
4649 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4650 else
4651 // data = R[t];
4652 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4653
4654 if (!success)
4655 return false;
4656
4657 EmulateInstruction::Context context;
4658 context.type = eContextRegisterStore;
4659
4660 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4661 if (UnalignedSupport ()
4662 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4663 || CurrentInstrSet() == eModeARM)
4664 {
4665 // MemU[address,4] = data;
4666
4667 Register base_reg;
4668 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4669
4670 Register data_reg;
4671 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4672
4673 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004674 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004675 return false;
4676
4677 }
4678 else
4679 // MemU[address,4] = bits(32) UNKNOWN;
4680 WriteBits32UnknownToMemory (address);
4681
4682 // if wback then R[n] = offset_addr;
4683 if (wback)
4684 {
4685 context.type = eContextRegisterLoad;
4686 context.SetAddress (offset_addr);
4687 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4688 return false;
4689 }
4690
4691 }
4692 return true;
4693}
Caroline Tice73a29de2011-02-16 20:22:22 +00004694
4695bool
4696EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4697{
4698#if 0
4699 if ConditionPassed() then
4700 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4701 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4702 address = if index then offset_addr else R[n];
4703 MemU[address,1] = R[t]<7:0>;
4704 if wback then R[n] = offset_addr;
4705#endif
4706
4707
4708 bool success = false;
4709 const uint32_t opcode = OpcodeAsUnsigned (&success);
4710 if (!success)
4711 return false;
4712
4713 if (ConditionPassed ())
4714 {
4715 uint32_t t;
4716 uint32_t n;
4717 uint32_t imm32;
4718 bool index;
4719 bool add;
4720 bool wback;
4721 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4722 switch (encoding)
4723 {
4724 case eEncodingT1:
4725 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4726 t = Bits32 (opcode, 2, 0);
4727 n = Bits32 (opcode, 5, 3);
4728 imm32 = Bits32 (opcode, 10, 6);
4729
4730 // index = TRUE; add = TRUE; wback = FALSE;
4731 index = true;
4732 add = true;
4733 wback = false;
4734 break;
4735
4736 case eEncodingT2:
4737 // if Rn == ’1111’ then UNDEFINED;
4738 if (Bits32 (opcode, 19, 16) == 15)
4739 return false;
4740
4741 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4742 t = Bits32 (opcode, 15, 12);
4743 n = Bits32 (opcode, 19, 16);
4744 imm32 = Bits32 (opcode, 11, 0);
4745
4746 // index = TRUE; add = TRUE; wback = FALSE;
4747 index = true;
4748 add = true;
4749 wback = false;
4750
4751 // if BadReg(t) then UNPREDICTABLE;
4752 if (BadReg (t))
4753 return false;
4754 break;
4755
4756 case eEncodingT3:
4757 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4758 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4759 if (Bits32 (opcode, 19, 16) == 15)
4760 return false;
4761
4762 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4763 t = Bits32 (opcode, 15, 12);
4764 n = Bits32 (opcode, 19, 16);
4765 imm32 = Bits32 (opcode, 7, 0);
4766
4767 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4768 index = BitIsSet (opcode, 10);
4769 add = BitIsSet (opcode, 9);
4770 wback = BitIsSet (opcode, 8);
4771
4772 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4773 if ((BadReg (t)) || (wback && (n == t)))
4774 return false;
4775 break;
4776
4777 default:
4778 return false;
4779 }
4780
4781 addr_t offset_addr;
4782 addr_t address;
4783 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4784 if (!success)
4785 return false;
4786
4787 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4788 if (add)
4789 offset_addr = base_address + imm32;
4790 else
4791 offset_addr = base_address - imm32;
4792
4793 // address = if index then offset_addr else R[n];
4794 if (index)
4795 address = offset_addr;
4796 else
4797 address = base_address;
4798
Caroline Ticecc96eb52011-02-17 19:20:40 +00004799 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004800 Register base_reg;
4801 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4802
4803 Register data_reg;
4804 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4805
4806 EmulateInstruction::Context context;
4807 context.type = eContextRegisterStore;
4808 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4809
4810 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4811 if (!success)
4812 return false;
4813
4814 data = Bits32 (data, 7, 0);
4815
Caroline Ticecc96eb52011-02-17 19:20:40 +00004816 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004817 return false;
4818
4819 // if wback then R[n] = offset_addr;
4820 if (wback)
4821 {
4822 context.type = eContextRegisterLoad;
4823 context.SetAddress (offset_addr);
4824 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4825 return false;
4826 }
4827
4828 }
4829
4830 return true;
4831}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004832
Johnny Chen157b9592011-02-18 21:13:05 +00004833// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4834// and writes the result to the destination register. It can optionally update the condition flags
4835// based on the result.
4836bool
4837EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4838{
4839#if 0
4840 // ARM pseudo code...
4841 if ConditionPassed() then
4842 EncodingSpecificOperations();
4843 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4844 if d == 15 then // Can only occur for ARM encoding
4845 ALUWritePC(result); // setflags is always FALSE here
4846 else
4847 R[d] = result;
4848 if setflags then
4849 APSR.N = result<31>;
4850 APSR.Z = IsZeroBit(result);
4851 APSR.C = carry;
4852 APSR.V = overflow;
4853#endif
4854
4855 bool success = false;
4856 const uint32_t opcode = OpcodeAsUnsigned (&success);
4857 if (!success)
4858 return false;
4859
4860 if (ConditionPassed())
4861 {
4862 uint32_t Rd, Rn;
4863 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4864 bool setflags;
4865 switch (encoding)
4866 {
4867 case eEncodingT1:
4868 Rd = Bits32(opcode, 11, 8);
4869 Rn = Bits32(opcode, 19, 16);
4870 setflags = BitIsSet(opcode, 20);
4871 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4872 if (BadReg(Rd) || BadReg(Rn))
4873 return false;
4874 break;
4875 case eEncodingA1:
4876 Rd = Bits32(opcode, 15, 12);
4877 Rn = Bits32(opcode, 19, 16);
4878 setflags = BitIsSet(opcode, 20);
4879 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4880 // TODO: Emulate SUBS PC, LR and related instructions.
4881 if (Rd == 15 && setflags)
4882 return false;
4883 break;
4884 default:
4885 return false;
4886 }
4887
4888 // Read the first operand.
4889 int32_t val1 = ReadCoreReg(Rn, &success);
4890 if (!success)
4891 return false;
4892
4893 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4894
4895 EmulateInstruction::Context context;
4896 context.type = EmulateInstruction::eContextImmediate;
4897 context.SetNoArgs ();
4898
4899 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4900 return false;
4901 }
4902 return true;
4903}
4904
4905// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4906// register value, and writes the result to the destination register. It can optionally update the
4907// condition flags based on the result.
4908bool
4909EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4910{
4911#if 0
4912 // ARM pseudo code...
4913 if ConditionPassed() then
4914 EncodingSpecificOperations();
4915 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4916 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4917 if d == 15 then // Can only occur for ARM encoding
4918 ALUWritePC(result); // setflags is always FALSE here
4919 else
4920 R[d] = result;
4921 if setflags then
4922 APSR.N = result<31>;
4923 APSR.Z = IsZeroBit(result);
4924 APSR.C = carry;
4925 APSR.V = overflow;
4926#endif
4927
4928 bool success = false;
4929 const uint32_t opcode = OpcodeAsUnsigned (&success);
4930 if (!success)
4931 return false;
4932
4933 if (ConditionPassed())
4934 {
4935 uint32_t Rd, Rn, Rm;
4936 ARM_ShifterType shift_t;
4937 uint32_t shift_n; // the shift applied to the value read from Rm
4938 bool setflags;
4939 switch (encoding)
4940 {
4941 case eEncodingT1:
4942 Rd = Rn = Bits32(opcode, 2, 0);
4943 Rm = Bits32(opcode, 5, 3);
4944 setflags = !InITBlock();
4945 shift_t = SRType_LSL;
4946 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004947 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004948 case eEncodingT2:
4949 Rd = Bits32(opcode, 11, 8);
4950 Rn = Bits32(opcode, 19, 16);
4951 Rm = Bits32(opcode, 3, 0);
4952 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004953 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004954 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4955 return false;
4956 break;
4957 case eEncodingA1:
4958 Rd = Bits32(opcode, 15, 12);
4959 Rn = Bits32(opcode, 19, 16);
4960 Rm = Bits32(opcode, 3, 0);
4961 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004962 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004963 // TODO: Emulate SUBS PC, LR and related instructions.
4964 if (Rd == 15 && setflags)
4965 return false;
4966 break;
4967 default:
4968 return false;
4969 }
4970
4971 // Read the first operand.
4972 int32_t val1 = ReadCoreReg(Rn, &success);
4973 if (!success)
4974 return false;
4975
4976 // Read the second operand.
4977 int32_t val2 = ReadCoreReg(Rm, &success);
4978 if (!success)
4979 return false;
4980
4981 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4982 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4983
4984 EmulateInstruction::Context context;
4985 context.type = EmulateInstruction::eContextImmediate;
4986 context.SetNoArgs ();
4987
4988 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4989 return false;
4990 }
4991 return true;
4992}
4993
Johnny Chena695f952011-02-23 21:24:25 +00004994// This instruction adds an immediate value to the PC value to form a PC-relative address,
4995// and writes the result to the destination register.
4996bool
4997EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4998{
4999#if 0
5000 // ARM pseudo code...
5001 if ConditionPassed() then
5002 EncodingSpecificOperations();
5003 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5004 if d == 15 then // Can only occur for ARM encodings
5005 ALUWritePC(result);
5006 else
5007 R[d] = result;
5008#endif
5009
5010 bool success = false;
5011 const uint32_t opcode = OpcodeAsUnsigned (&success);
5012 if (!success)
5013 return false;
5014
5015 if (ConditionPassed())
5016 {
5017 uint32_t Rd;
5018 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5019 bool add;
5020 switch (encoding)
5021 {
5022 case eEncodingT1:
5023 Rd = Bits32(opcode, 10, 8);
5024 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5025 break;
5026 case eEncodingT2:
5027 case eEncodingT3:
5028 Rd = Bits32(opcode, 11, 8);
5029 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5030 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5031 if (BadReg(Rd))
5032 return false;
5033 break;
5034 case eEncodingA1:
5035 case eEncodingA2:
5036 Rd = Bits32(opcode, 15, 12);
5037 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5038 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5039 break;
5040 default:
5041 return false;
5042 }
5043
5044 // Read the PC value.
5045 uint32_t pc = ReadCoreReg(PC_REG, &success);
5046 if (!success)
5047 return false;
5048
5049 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5050
5051 EmulateInstruction::Context context;
5052 context.type = EmulateInstruction::eContextImmediate;
5053 context.SetNoArgs ();
5054
5055 if (!WriteCoreReg(context, result, Rd))
5056 return false;
5057 }
5058 return true;
5059}
5060
Johnny Chene97c0d52011-02-18 19:32:20 +00005061// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5062// to the destination register. It can optionally update the condition flags based on the result.
5063bool
5064EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5065{
5066#if 0
5067 // ARM pseudo code...
5068 if ConditionPassed() then
5069 EncodingSpecificOperations();
5070 result = R[n] AND imm32;
5071 if d == 15 then // Can only occur for ARM encoding
5072 ALUWritePC(result); // setflags is always FALSE here
5073 else
5074 R[d] = result;
5075 if setflags then
5076 APSR.N = result<31>;
5077 APSR.Z = IsZeroBit(result);
5078 APSR.C = carry;
5079 // APSR.V unchanged
5080#endif
5081
5082 bool success = false;
5083 const uint32_t opcode = OpcodeAsUnsigned (&success);
5084 if (!success)
5085 return false;
5086
5087 if (ConditionPassed())
5088 {
5089 uint32_t Rd, Rn;
5090 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5091 bool setflags;
5092 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5093 switch (encoding)
5094 {
5095 case eEncodingT1:
5096 Rd = Bits32(opcode, 11, 8);
5097 Rn = Bits32(opcode, 19, 16);
5098 setflags = BitIsSet(opcode, 20);
5099 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005100 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005101 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005102 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005103 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5104 return false;
5105 break;
5106 case eEncodingA1:
5107 Rd = Bits32(opcode, 15, 12);
5108 Rn = Bits32(opcode, 19, 16);
5109 setflags = BitIsSet(opcode, 20);
5110 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5111 // TODO: Emulate SUBS PC, LR and related instructions.
5112 if (Rd == 15 && setflags)
5113 return false;
5114 break;
5115 default:
5116 return false;
5117 }
5118
Johnny Chene97c0d52011-02-18 19:32:20 +00005119 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005120 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005121 if (!success)
5122 return false;
5123
5124 uint32_t result = val1 & imm32;
5125
5126 EmulateInstruction::Context context;
5127 context.type = EmulateInstruction::eContextImmediate;
5128 context.SetNoArgs ();
5129
5130 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5131 return false;
5132 }
5133 return true;
5134}
5135
5136// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5137// and writes the result to the destination register. It can optionally update the condition flags
5138// based on the result.
5139bool
5140EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5141{
5142#if 0
5143 // ARM pseudo code...
5144 if ConditionPassed() then
5145 EncodingSpecificOperations();
5146 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5147 result = R[n] AND shifted;
5148 if d == 15 then // Can only occur for ARM encoding
5149 ALUWritePC(result); // setflags is always FALSE here
5150 else
5151 R[d] = result;
5152 if setflags then
5153 APSR.N = result<31>;
5154 APSR.Z = IsZeroBit(result);
5155 APSR.C = carry;
5156 // APSR.V unchanged
5157#endif
5158
5159 bool success = false;
5160 const uint32_t opcode = OpcodeAsUnsigned (&success);
5161 if (!success)
5162 return false;
5163
5164 if (ConditionPassed())
5165 {
5166 uint32_t Rd, Rn, Rm;
5167 ARM_ShifterType shift_t;
5168 uint32_t shift_n; // the shift applied to the value read from Rm
5169 bool setflags;
5170 uint32_t carry;
5171 switch (encoding)
5172 {
5173 case eEncodingT1:
5174 Rd = Rn = Bits32(opcode, 2, 0);
5175 Rm = Bits32(opcode, 5, 3);
5176 setflags = !InITBlock();
5177 shift_t = SRType_LSL;
5178 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005179 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005180 case eEncodingT2:
5181 Rd = Bits32(opcode, 11, 8);
5182 Rn = Bits32(opcode, 19, 16);
5183 Rm = Bits32(opcode, 3, 0);
5184 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005185 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005186 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005187 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005188 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005189 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5190 return false;
5191 break;
5192 case eEncodingA1:
5193 Rd = Bits32(opcode, 15, 12);
5194 Rn = Bits32(opcode, 19, 16);
5195 Rm = Bits32(opcode, 3, 0);
5196 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005197 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005198 // TODO: Emulate SUBS PC, LR and related instructions.
5199 if (Rd == 15 && setflags)
5200 return false;
5201 break;
5202 default:
5203 return false;
5204 }
5205
Johnny Chene97c0d52011-02-18 19:32:20 +00005206 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005207 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005208 if (!success)
5209 return false;
5210
5211 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005212 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005213 if (!success)
5214 return false;
5215
5216 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5217 uint32_t result = val1 & shifted;
5218
5219 EmulateInstruction::Context context;
5220 context.type = EmulateInstruction::eContextImmediate;
5221 context.SetNoArgs ();
5222
5223 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5224 return false;
5225 }
5226 return true;
5227}
5228
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005229// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5230// immediate value, and writes the result to the destination register. It can optionally update the
5231// condition flags based on the result.
5232bool
5233EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5234{
5235#if 0
5236 // ARM pseudo code...
5237 if ConditionPassed() then
5238 EncodingSpecificOperations();
5239 result = R[n] AND NOT(imm32);
5240 if d == 15 then // Can only occur for ARM encoding
5241 ALUWritePC(result); // setflags is always FALSE here
5242 else
5243 R[d] = result;
5244 if setflags then
5245 APSR.N = result<31>;
5246 APSR.Z = IsZeroBit(result);
5247 APSR.C = carry;
5248 // APSR.V unchanged
5249#endif
5250
5251 bool success = false;
5252 const uint32_t opcode = OpcodeAsUnsigned (&success);
5253 if (!success)
5254 return false;
5255
5256 if (ConditionPassed())
5257 {
5258 uint32_t Rd, Rn;
5259 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5260 bool setflags;
5261 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5262 switch (encoding)
5263 {
5264 case eEncodingT1:
5265 Rd = Bits32(opcode, 11, 8);
5266 Rn = Bits32(opcode, 19, 16);
5267 setflags = BitIsSet(opcode, 20);
5268 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5269 if (BadReg(Rd) || BadReg(Rn))
5270 return false;
5271 break;
5272 case eEncodingA1:
5273 Rd = Bits32(opcode, 15, 12);
5274 Rn = Bits32(opcode, 19, 16);
5275 setflags = BitIsSet(opcode, 20);
5276 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5277 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5278 // TODO: Emulate SUBS PC, LR and related instructions.
5279 if (Rd == 15 && setflags)
5280 return false;
5281 break;
5282 default:
5283 return false;
5284 }
5285
5286 // Read the first operand.
5287 uint32_t val1 = ReadCoreReg(Rn, &success);
5288 if (!success)
5289 return false;
5290
5291 uint32_t result = val1 & ~imm32;
5292
5293 EmulateInstruction::Context context;
5294 context.type = EmulateInstruction::eContextImmediate;
5295 context.SetNoArgs ();
5296
5297 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5298 return false;
5299 }
5300 return true;
5301}
5302
5303// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5304// optionally-shifted register value, and writes the result to the destination register.
5305// It can optionally update the condition flags based on the result.
5306bool
5307EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5308{
5309#if 0
5310 // ARM pseudo code...
5311 if ConditionPassed() then
5312 EncodingSpecificOperations();
5313 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5314 result = R[n] AND NOT(shifted);
5315 if d == 15 then // Can only occur for ARM encoding
5316 ALUWritePC(result); // setflags is always FALSE here
5317 else
5318 R[d] = result;
5319 if setflags then
5320 APSR.N = result<31>;
5321 APSR.Z = IsZeroBit(result);
5322 APSR.C = carry;
5323 // APSR.V unchanged
5324#endif
5325
5326 bool success = false;
5327 const uint32_t opcode = OpcodeAsUnsigned (&success);
5328 if (!success)
5329 return false;
5330
5331 if (ConditionPassed())
5332 {
5333 uint32_t Rd, Rn, Rm;
5334 ARM_ShifterType shift_t;
5335 uint32_t shift_n; // the shift applied to the value read from Rm
5336 bool setflags;
5337 uint32_t carry;
5338 switch (encoding)
5339 {
5340 case eEncodingT1:
5341 Rd = Rn = Bits32(opcode, 2, 0);
5342 Rm = Bits32(opcode, 5, 3);
5343 setflags = !InITBlock();
5344 shift_t = SRType_LSL;
5345 shift_n = 0;
5346 break;
5347 case eEncodingT2:
5348 Rd = Bits32(opcode, 11, 8);
5349 Rn = Bits32(opcode, 19, 16);
5350 Rm = Bits32(opcode, 3, 0);
5351 setflags = BitIsSet(opcode, 20);
5352 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5353 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5354 return false;
5355 break;
5356 case eEncodingA1:
5357 Rd = Bits32(opcode, 15, 12);
5358 Rn = Bits32(opcode, 19, 16);
5359 Rm = Bits32(opcode, 3, 0);
5360 setflags = BitIsSet(opcode, 20);
5361 shift_n = DecodeImmShiftARM(opcode, shift_t);
5362 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5363 // TODO: Emulate SUBS PC, LR and related instructions.
5364 if (Rd == 15 && setflags)
5365 return false;
5366 break;
5367 default:
5368 return false;
5369 }
5370
5371 // Read the first operand.
5372 uint32_t val1 = ReadCoreReg(Rn, &success);
5373 if (!success)
5374 return false;
5375
5376 // Read the second operand.
5377 uint32_t val2 = ReadCoreReg(Rm, &success);
5378 if (!success)
5379 return false;
5380
5381 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5382 uint32_t result = val1 & ~shifted;
5383
5384 EmulateInstruction::Context context;
5385 context.type = EmulateInstruction::eContextImmediate;
5386 context.SetNoArgs ();
5387
5388 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5389 return false;
5390 }
5391 return true;
5392}
5393
Caroline Tice4d729c52011-02-18 00:55:53 +00005394// 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 +00005395// 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 +00005396bool
5397EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5398{
5399#if 0
5400 if ConditionPassed() then
5401 EncodingSpecificOperations();
5402 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5403 address = if index then offset_addr else R[n];
5404 data = MemU[address,4];
5405 if wback then R[n] = offset_addr;
5406 if t == 15 then
5407 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5408 elsif UnalignedSupport() || address<1:0> = ’00’ then
5409 R[t] = data;
5410 else // Can only apply before ARMv7
5411 R[t] = ROR(data, 8*UInt(address<1:0>));
5412#endif
5413
5414 bool success = false;
5415 const uint32_t opcode = OpcodeAsUnsigned (&success);
5416 if (!success)
5417 return false;
5418
5419 if (ConditionPassed ())
5420 {
5421 const uint32_t addr_byte_size = GetAddressByteSize();
5422
5423 uint32_t t;
5424 uint32_t n;
5425 uint32_t imm32;
5426 bool index;
5427 bool add;
5428 bool wback;
5429
5430 switch (encoding)
5431 {
5432 case eEncodingA1:
5433 // if Rn == ’1111’ then SEE LDR (literal);
5434 // if P == ’0’ && W == ’1’ then SEE LDRT;
5435 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5436 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5437 t = Bits32 (opcode, 15, 12);
5438 n = Bits32 (opcode, 19, 16);
5439 imm32 = Bits32 (opcode, 11, 0);
5440
5441 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5442 index = BitIsSet (opcode, 24);
5443 add = BitIsSet (opcode, 23);
5444 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5445
5446 // if wback && n == t then UNPREDICTABLE;
5447 if (wback && (n == t))
5448 return false;
5449
5450 break;
5451
5452 default:
5453 return false;
5454 }
5455
5456 addr_t address;
5457 addr_t offset_addr;
5458 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5459 if (!success)
5460 return false;
5461
5462 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5463 if (add)
5464 offset_addr = base_address + imm32;
5465 else
5466 offset_addr = base_address - imm32;
5467
5468 // address = if index then offset_addr else R[n];
5469 if (index)
5470 address = offset_addr;
5471 else
5472 address = base_address;
5473
5474 // data = MemU[address,4];
5475
5476 Register base_reg;
5477 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5478
5479 EmulateInstruction::Context context;
5480 context.type = eContextRegisterLoad;
5481 context.SetRegisterPlusOffset (base_reg, address - base_address);
5482
5483 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5484 if (!success)
5485 return false;
5486
5487 // if wback then R[n] = offset_addr;
5488 if (wback)
5489 {
5490 context.type = eContextAdjustBaseRegister;
5491 context.SetAddress (offset_addr);
5492 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5493 return false;
5494 }
5495
5496 // if t == 15 then
5497 if (t == 15)
5498 {
5499 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5500 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5501 {
5502 // LoadWritePC (data);
5503 context.type = eContextRegisterLoad;
5504 context.SetRegisterPlusOffset (base_reg, address - base_address);
5505 LoadWritePC (context, data);
5506 }
5507 else
5508 return false;
5509 }
5510 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5511 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5512 {
5513 // R[t] = data;
5514 context.type = eContextRegisterLoad;
5515 context.SetRegisterPlusOffset (base_reg, address - base_address);
5516 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5517 return false;
5518 }
5519 // else // Can only apply before ARMv7
5520 else
5521 {
5522 // R[t] = ROR(data, 8*UInt(address<1:0>));
5523 data = ROR (data, Bits32 (address, 1, 0));
5524 context.type = eContextRegisterLoad;
5525 context.SetImmediate (data);
5526 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5527 return false;
5528 }
5529
5530 }
5531 return true;
5532}
5533
Caroline Ticefe479112011-02-18 18:52:37 +00005534// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5535// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5536bool
5537EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5538{
5539#if 0
5540 if ConditionPassed() then
5541 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5542 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5543 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5544 address = if index then offset_addr else R[n];
5545 data = MemU[address,4];
5546 if wback then R[n] = offset_addr;
5547 if t == 15 then
5548 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5549 elsif UnalignedSupport() || address<1:0> = ’00’ then
5550 R[t] = data;
5551 else // Can only apply before ARMv7
5552 if CurrentInstrSet() == InstrSet_ARM then
5553 R[t] = ROR(data, 8*UInt(address<1:0>));
5554 else
5555 R[t] = bits(32) UNKNOWN;
5556#endif
5557
5558 bool success = false;
5559 const uint32_t opcode = OpcodeAsUnsigned (&success);
5560 if (!success)
5561 return false;
5562
5563 if (ConditionPassed ())
5564 {
5565 const uint32_t addr_byte_size = GetAddressByteSize();
5566
5567 uint32_t t;
5568 uint32_t n;
5569 uint32_t m;
5570 bool index;
5571 bool add;
5572 bool wback;
5573 ARM_ShifterType shift_t;
5574 uint32_t shift_n;
5575
5576 switch (encoding)
5577 {
5578 case eEncodingT1:
5579 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5580 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5581 t = Bits32 (opcode, 2, 0);
5582 n = Bits32 (opcode, 5, 3);
5583 m = Bits32 (opcode, 8, 6);
5584
5585 // index = TRUE; add = TRUE; wback = FALSE;
5586 index = true;
5587 add = true;
5588 wback = false;
5589
5590 // (shift_t, shift_n) = (SRType_LSL, 0);
5591 shift_t = SRType_LSL;
5592 shift_n = 0;
5593
5594 break;
5595
5596 case eEncodingT2:
5597 // if Rn == ’1111’ then SEE LDR (literal);
5598 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5599 t = Bits32 (opcode, 15, 12);
5600 n = Bits32 (opcode, 19, 16);
5601 m = Bits32 (opcode, 3, 0);
5602
5603 // index = TRUE; add = TRUE; wback = FALSE;
5604 index = true;
5605 add = true;
5606 wback = false;
5607
5608 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5609 shift_t = SRType_LSL;
5610 shift_n = Bits32 (opcode, 5, 4);
5611
5612 // if BadReg(m) then UNPREDICTABLE;
5613 if (BadReg (m))
5614 return false;
5615
5616 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5617 if ((t == 15) && InITBlock() && !LastInITBlock())
5618 return false;
5619
5620 break;
5621
5622 case eEncodingA1:
5623 {
5624 // if P == ’0’ && W == ’1’ then SEE LDRT;
5625 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5626 t = Bits32 (opcode, 15, 12);
5627 n = Bits32 (opcode, 19, 16);
5628 m = Bits32 (opcode, 3, 0);
5629
5630 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5631 index = BitIsSet (opcode, 24);
5632 add = BitIsSet (opcode, 23);
5633 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5634
5635 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5636 uint32_t type = Bits32 (opcode, 6, 5);
5637 uint32_t imm5 = Bits32 (opcode, 11, 7);
5638 shift_n = DecodeImmShift (type, imm5, shift_t);
5639
5640 // if m == 15 then UNPREDICTABLE;
5641 if (m == 15)
5642 return false;
5643
5644 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5645 if (wback && ((n == 15) || (n == t)))
5646 return false;
5647 }
5648 break;
5649
5650
5651 default:
5652 return false;
5653 }
5654
5655 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5656 if (!success)
5657 return false;
5658
5659 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5660 if (!success)
5661 return false;
5662
5663 addr_t offset_addr;
5664 addr_t address;
5665
5666 // 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 +00005667 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005668
5669 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5670 if (add)
5671 offset_addr = Rn + offset;
5672 else
5673 offset_addr = Rn - offset;
5674
5675 // address = if index then offset_addr else R[n];
5676 if (index)
5677 address = offset_addr;
5678 else
5679 address = Rn;
5680
5681 // data = MemU[address,4];
5682 Register base_reg;
5683 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5684
5685 EmulateInstruction::Context context;
5686 context.type = eContextRegisterLoad;
5687 context.SetRegisterPlusOffset (base_reg, address - Rn);
5688
5689 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5690 if (!success)
5691 return false;
5692
5693 // if wback then R[n] = offset_addr;
5694 if (wback)
5695 {
5696 context.type = eContextAdjustBaseRegister;
5697 context.SetAddress (offset_addr);
5698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5699 return false;
5700 }
5701
5702 // if t == 15 then
5703 if (t == 15)
5704 {
5705 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5706 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5707 {
5708 context.type = eContextRegisterLoad;
5709 context.SetRegisterPlusOffset (base_reg, address - Rn);
5710 LoadWritePC (context, data);
5711 }
5712 else
5713 return false;
5714 }
5715 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5716 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5717 {
5718 // R[t] = data;
5719 context.type = eContextRegisterLoad;
5720 context.SetRegisterPlusOffset (base_reg, address - Rn);
5721 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5722 return false;
5723 }
5724 else // Can only apply before ARMv7
5725 {
5726 // if CurrentInstrSet() == InstrSet_ARM then
5727 if (CurrentInstrSet () == eModeARM)
5728 {
5729 // R[t] = ROR(data, 8*UInt(address<1:0>));
5730 data = ROR (data, Bits32 (address, 1, 0));
5731 context.type = eContextRegisterLoad;
5732 context.SetImmediate (data);
5733 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5734 return false;
5735 }
5736 else
5737 {
5738 // R[t] = bits(32) UNKNOWN;
5739 WriteBits32Unknown (t);
5740 }
5741 }
5742 }
5743 return true;
5744}
Caroline Tice21b604b2011-02-18 21:06:04 +00005745
5746// LDRB (immediate, Thumb)
5747bool
5748EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5749{
5750#if 0
5751 if ConditionPassed() then
5752 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5753 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5754 address = if index then offset_addr else R[n];
5755 R[t] = ZeroExtend(MemU[address,1], 32);
5756 if wback then R[n] = offset_addr;
5757#endif
5758
5759 bool success = false;
5760 const uint32_t opcode = OpcodeAsUnsigned (&success);
5761 if (!success)
5762 return false;
5763
5764 if (ConditionPassed ())
5765 {
5766 uint32_t t;
5767 uint32_t n;
5768 uint32_t imm32;
5769 bool index;
5770 bool add;
5771 bool wback;
5772
5773 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5774 switch (encoding)
5775 {
5776 case eEncodingT1:
5777 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5778 t = Bits32 (opcode, 2, 0);
5779 n = Bits32 (opcode, 5, 3);
5780 imm32 = Bits32 (opcode, 10, 6);
5781
5782 // index = TRUE; add = TRUE; wback = FALSE;
5783 index = true;
5784 add = true;
5785 wback= false;
5786
5787 break;
5788
5789 case eEncodingT2:
5790 // if Rt == ’1111’ then SEE PLD;
5791 // if Rn == ’1111’ then SEE LDRB (literal);
5792 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5793 t = Bits32 (opcode, 15, 12);
5794 n = Bits32 (opcode, 19, 16);
5795 imm32 = Bits32 (opcode, 11, 0);
5796
5797 // index = TRUE; add = TRUE; wback = FALSE;
5798 index = true;
5799 add = true;
5800 wback = false;
5801
5802 // if t == 13 then UNPREDICTABLE;
5803 if (t == 13)
5804 return false;
5805
5806 break;
5807
5808 case eEncodingT3:
5809 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5810 // if Rn == ’1111’ then SEE LDRB (literal);
5811 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5812 // if P == ’0’ && W == ’0’ then UNDEFINED;
5813 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5814 return false;
5815
5816 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5817 t = Bits32 (opcode, 15, 12);
5818 n = Bits32 (opcode, 19, 16);
5819 imm32 = Bits32 (opcode, 7, 0);
5820
5821 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5822 index = BitIsSet (opcode, 10);
5823 add = BitIsSet (opcode, 9);
5824 wback = BitIsSet (opcode, 8);
5825
5826 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5827 if (BadReg (t) || (wback && (n == t)))
5828 return false;
5829
5830 break;
5831
5832 default:
5833 return false;
5834 }
5835
5836 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5837 if (!success)
5838 return false;
5839
5840 addr_t address;
5841 addr_t offset_addr;
5842
5843 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5844 if (add)
5845 offset_addr = Rn + imm32;
5846 else
5847 offset_addr = Rn - imm32;
5848
5849 // address = if index then offset_addr else R[n];
5850 if (index)
5851 address = offset_addr;
5852 else
5853 address = Rn;
5854
5855 // R[t] = ZeroExtend(MemU[address,1], 32);
5856 Register base_reg;
5857 Register data_reg;
5858 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5859 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5860
5861 EmulateInstruction::Context context;
5862 context.type = eContextRegisterLoad;
5863 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5864
5865 uint64_t data = MemURead (context, address, 1, 0, &success);
5866 if (!success)
5867 return false;
5868
5869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5870 return false;
5871
5872 // if wback then R[n] = offset_addr;
5873 if (wback)
5874 {
5875 context.type = eContextAdjustBaseRegister;
5876 context.SetAddress (offset_addr);
5877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5878 return false;
5879 }
5880 }
5881 return true;
5882}
Caroline Ticef55261f2011-02-18 22:24:22 +00005883
5884// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5885// zero-extends it to form a 32-bit word and writes it to a register.
5886bool
5887EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5888{
5889#if 0
5890 if ConditionPassed() then
5891 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5892 base = Align(PC,4);
5893 address = if add then (base + imm32) else (base - imm32);
5894 R[t] = ZeroExtend(MemU[address,1], 32);
5895#endif
5896
5897 bool success = false;
5898 const uint32_t opcode = OpcodeAsUnsigned (&success);
5899 if (!success)
5900 return false;
5901
5902 if (ConditionPassed ())
5903 {
5904 uint32_t t;
5905 uint32_t imm32;
5906 bool add;
5907 switch (encoding)
5908 {
5909 case eEncodingT1:
5910 // if Rt == ’1111’ then SEE PLD;
5911 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5912 t = Bits32 (opcode, 15, 12);
5913 imm32 = Bits32 (opcode, 11, 0);
5914 add = BitIsSet (opcode, 23);
5915
5916 // if t == 13 then UNPREDICTABLE;
5917 if (t == 13)
5918 return false;
5919
5920 break;
5921
5922 case eEncodingA1:
5923 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5924 t = Bits32 (opcode, 15, 12);
5925 imm32 = Bits32 (opcode, 11, 0);
5926 add = BitIsSet (opcode, 23);
5927
5928 // if t == 15 then UNPREDICTABLE;
5929 if (t == 15)
5930 return false;
5931 break;
5932
5933 default:
5934 return false;
5935 }
5936
5937 // base = Align(PC,4);
5938 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5939 if (!success)
5940 return false;
5941
5942 uint32_t base = AlignPC (pc_val);
5943
5944 addr_t address;
5945 // address = if add then (base + imm32) else (base - imm32);
5946 if (add)
5947 address = base + imm32;
5948 else
5949 address = base - imm32;
5950
5951 // R[t] = ZeroExtend(MemU[address,1], 32);
5952 EmulateInstruction::Context context;
5953 context.type = eContextRelativeBranchImmediate;
5954 context.SetImmediate (address - base);
5955
5956 uint64_t data = MemURead (context, address, 1, 0, &success);
5957 if (!success)
5958 return false;
5959
5960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5961 return false;
5962 }
5963 return true;
5964}
Caroline Tice30fec122011-02-18 23:52:21 +00005965
5966// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5967// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5968// optionally be shifted.
5969bool
5970EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5971{
5972#if 0
5973 if ConditionPassed() then
5974 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5975 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5976 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5977 address = if index then offset_addr else R[n];
5978 R[t] = ZeroExtend(MemU[address,1],32);
5979 if wback then R[n] = offset_addr;
5980#endif
5981
5982 bool success = false;
5983 const uint32_t opcode = OpcodeAsUnsigned (&success);
5984 if (!success)
5985 return false;
5986
5987 if (ConditionPassed ())
5988 {
5989 uint32_t t;
5990 uint32_t n;
5991 uint32_t m;
5992 bool index;
5993 bool add;
5994 bool wback;
5995 ARM_ShifterType shift_t;
5996 uint32_t shift_n;
5997
5998 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5999 switch (encoding)
6000 {
6001 case eEncodingT1:
6002 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6003 t = Bits32 (opcode, 2, 0);
6004 n = Bits32 (opcode, 5, 3);
6005 m = Bits32 (opcode, 8, 6);
6006
6007 // index = TRUE; add = TRUE; wback = FALSE;
6008 index = true;
6009 add = true;
6010 wback = false;
6011
6012 // (shift_t, shift_n) = (SRType_LSL, 0);
6013 shift_t = SRType_LSL;
6014 shift_n = 0;
6015 break;
6016
6017 case eEncodingT2:
6018 // if Rt == ’1111’ then SEE PLD;
6019 // if Rn == ’1111’ then SEE LDRB (literal);
6020 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6021 t = Bits32 (opcode, 15, 12);
6022 n = Bits32 (opcode, 19, 16);
6023 m = Bits32 (opcode, 3, 0);
6024
6025 // index = TRUE; add = TRUE; wback = FALSE;
6026 index = true;
6027 add = true;
6028 wback = false;
6029
6030 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6031 shift_t = SRType_LSL;
6032 shift_n = Bits32 (opcode, 5, 4);
6033
6034 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6035 if ((t == 13) || BadReg (m))
6036 return false;
6037 break;
6038
6039 case eEncodingA1:
6040 {
6041 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6042 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6043 t = Bits32 (opcode, 15, 12);
6044 n = Bits32 (opcode, 19, 16);
6045 m = Bits32 (opcode, 3, 0);
6046
6047 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6048 index = BitIsSet (opcode, 24);
6049 add = BitIsSet (opcode, 23);
6050 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6051
6052 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6053 uint32_t type = Bits32 (opcode, 6, 5);
6054 uint32_t imm5 = Bits32 (opcode, 11, 7);
6055 shift_n = DecodeImmShift (type, imm5, shift_t);
6056
6057 // if t == 15 || m == 15 then UNPREDICTABLE;
6058 if ((t == 15) || (m == 15))
6059 return false;
6060
6061 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6062 if (wback && ((n == 15) || (n == t)))
6063 return false;
6064 }
6065 break;
6066
6067 default:
6068 return false;
6069 }
6070
6071 addr_t offset_addr;
6072 addr_t address;
6073
6074 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6075 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6076 if (!success)
6077 return false;
6078
6079 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6080
6081 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6082 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6083 if (!success)
6084 return false;
6085
6086 if (add)
6087 offset_addr = Rn + offset;
6088 else
6089 offset_addr = Rn - offset;
6090
6091 // address = if index then offset_addr else R[n];
6092 if (index)
6093 address = offset_addr;
6094 else
6095 address = Rn;
6096
6097 // R[t] = ZeroExtend(MemU[address,1],32);
6098 Register base_reg;
6099 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6100
6101 EmulateInstruction::Context context;
6102 context.type = eContextRegisterLoad;
6103 context.SetRegisterPlusOffset (base_reg, address - Rn);
6104
6105 uint64_t data = MemURead (context, address, 1, 0, &success);
6106 if (!success)
6107 return false;
6108
6109 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6110 return false;
6111
6112 // if wback then R[n] = offset_addr;
6113 if (wback)
6114 {
6115 context.type = eContextAdjustBaseRegister;
6116 context.SetAddress (offset_addr);
6117 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6118 return false;
6119 }
6120 }
6121 return true;
6122}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006123
6124// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6125// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6126// post-indexed, or pre-indexed addressing.
6127bool
6128EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6129{
6130#if 0
6131 if ConditionPassed() then
6132 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6133 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6134 address = if index then offset_addr else R[n];
6135 data = MemU[address,2];
6136 if wback then R[n] = offset_addr;
6137 if UnalignedSupport() || address<0> = ’0’ then
6138 R[t] = ZeroExtend(data, 32);
6139 else // Can only apply before ARMv7
6140 R[t] = bits(32) UNKNOWN;
6141#endif
6142
6143
6144 bool success = false;
6145 const uint32_t opcode = OpcodeAsUnsigned (&success);
6146 if (!success)
6147 return false;
6148
6149 if (ConditionPassed())
6150 {
6151 uint32_t t;
6152 uint32_t n;
6153 uint32_t imm32;
6154 bool index;
6155 bool add;
6156 bool wback;
6157
6158 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6159 switch (encoding)
6160 {
6161 case eEncodingT1:
6162 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6163 t = Bits32 (opcode, 2, 0);
6164 n = Bits32 (opcode, 5, 3);
6165 imm32 = Bits32 (opcode, 10, 6) << 1;
6166
6167 // index = TRUE; add = TRUE; wback = FALSE;
6168 index = true;
6169 add = true;
6170 wback = false;
6171
6172 break;
6173
6174 case eEncodingT2:
6175 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6176 // if Rn == ’1111’ then SEE LDRH (literal);
6177 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6178 t = Bits32 (opcode, 15, 12);
6179 n = Bits32 (opcode, 19, 16);
6180 imm32 = Bits32 (opcode, 11, 0);
6181
6182 // index = TRUE; add = TRUE; wback = FALSE;
6183 index = true;
6184 add = true;
6185 wback = false;
6186
6187 // if t == 13 then UNPREDICTABLE;
6188 if (t == 13)
6189 return false;
6190 break;
6191
6192 case eEncodingT3:
6193 // if Rn == ’1111’ then SEE LDRH (literal);
6194 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6195 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6196 // if P == ’0’ && W == ’0’ then UNDEFINED;
6197 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6198 return false;
6199
6200 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6201 t = Bits32 (opcode, 15, 12);
6202 n = Bits32 (opcode, 19, 16);
6203 imm32 = Bits32 (opcode, 7, 0);
6204
6205 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6206 index = BitIsSet (opcode, 10);
6207 add = BitIsSet (opcode, 9);
6208 wback = BitIsSet (opcode, 8);
6209
6210 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6211 if (BadReg (t) || (wback && (n == t)))
6212 return false;
6213 break;
6214
6215 default:
6216 return false;
6217 }
6218
6219 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6220 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6221 if (!success)
6222 return false;
6223
6224 addr_t offset_addr;
6225 addr_t address;
6226
6227 if (add)
6228 offset_addr = Rn + imm32;
6229 else
6230 offset_addr = Rn - imm32;
6231
6232 // address = if index then offset_addr else R[n];
6233 if (index)
6234 address = offset_addr;
6235 else
6236 address = Rn;
6237
6238 // data = MemU[address,2];
6239 Register base_reg;
6240 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6241
6242 EmulateInstruction::Context context;
6243 context.type = eContextRegisterLoad;
6244 context.SetRegisterPlusOffset (base_reg, address - Rn);
6245
6246 uint64_t data = MemURead (context, address, 2, 0, &success);
6247 if (!success)
6248 return false;
6249
6250 // if wback then R[n] = offset_addr;
6251 if (wback)
6252 {
6253 context.type = eContextAdjustBaseRegister;
6254 context.SetAddress (offset_addr);
6255 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6256 return false;
6257 }
6258
6259 // if UnalignedSupport() || address<0> = ’0’ then
6260 if (UnalignedSupport () || BitIsClear (address, 0))
6261 {
6262 // R[t] = ZeroExtend(data, 32);
6263 context.type = eContextRegisterLoad;
6264 context.SetRegisterPlusOffset (base_reg, address - Rn);
6265 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6266 return false;
6267 }
6268 else // Can only apply before ARMv7
6269 {
6270 // R[t] = bits(32) UNKNOWN;
6271 WriteBits32Unknown (t);
6272 }
6273 }
6274 return true;
6275}
Caroline Ticefe479112011-02-18 18:52:37 +00006276
Caroline Tice952b5382011-02-28 23:15:24 +00006277// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6278// zero-extends it to form a 32-bit word, and writes it to a register.
6279bool
6280EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6281{
6282#if 0
6283 if ConditionPassed() then
6284 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6285 base = Align(PC,4);
6286 address = if add then (base + imm32) else (base - imm32);
6287 data = MemU[address,2];
6288 if UnalignedSupport() || address<0> = ’0’ then
6289 R[t] = ZeroExtend(data, 32);
6290 else // Can only apply before ARMv7
6291 R[t] = bits(32) UNKNOWN;
6292#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006293
Caroline Tice952b5382011-02-28 23:15:24 +00006294 bool success = false;
6295 const uint32_t opcode = OpcodeAsUnsigned (&success);
6296 if (!success)
6297 return false;
6298
6299 if (ConditionPassed())
6300 {
6301 uint32_t t;
6302 uint32_t imm32;
6303 bool add;
6304
6305 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6306 switch (encoding)
6307 {
6308 case eEncodingT1:
6309 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6310 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6311 t = Bits32 (opcode, 15, 12);
6312 imm32 = Bits32 (opcode, 11, 0);
6313 add = BitIsSet (opcode, 23);
6314
6315 // if t == 13 then UNPREDICTABLE;
6316 if (t == 13)
6317 return false;
6318
6319 break;
6320
6321 case eEncodingA1:
6322 {
6323 uint32_t imm4H = Bits32 (opcode, 11, 8);
6324 uint32_t imm4L = Bits32 (opcode, 3, 0);
6325
6326 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6327 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006328 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006329 add = BitIsSet (opcode, 23);
6330
6331 // if t == 15 then UNPREDICTABLE;
6332 if (t == 15)
6333 return false;
6334 break;
6335 }
6336
6337 default:
6338 return false;
6339 }
6340
6341 // base = Align(PC,4);
6342 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6343 if (!success)
6344 return false;
6345
6346 addr_t base = AlignPC (pc_value);
6347 addr_t address;
6348
6349 // address = if add then (base + imm32) else (base - imm32);
6350 if (add)
6351 address = base + imm32;
6352 else
6353 address = base - imm32;
6354
6355 // data = MemU[address,2];
6356 Register base_reg;
6357 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6358
6359 EmulateInstruction::Context context;
6360 context.type = eContextRegisterLoad;
6361 context.SetRegisterPlusOffset (base_reg, address - base);
6362
6363 uint64_t data = MemURead (context, address, 2, 0, &success);
6364 if (!success)
6365 return false;
6366
6367
6368 // if UnalignedSupport() || address<0> = ’0’ then
6369 if (UnalignedSupport () || BitIsClear (address, 0))
6370 {
6371 // R[t] = ZeroExtend(data, 32);
6372 context.type = eContextRegisterLoad;
6373 context.SetRegisterPlusOffset (base_reg, address - base);
6374 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6375 return false;
6376
6377 }
6378 else // Can only apply before ARMv7
6379 {
6380 // R[t] = bits(32) UNKNOWN;
6381 WriteBits32Unknown (t);
6382 }
6383 }
6384 return true;
6385}
6386
Caroline Tice0e6bc952011-03-01 18:00:42 +00006387// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6388// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6389// be shifted left by 0, 1, 2, or 3 bits.
6390bool
6391EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6392{
6393#if 0
6394 if ConditionPassed() then
6395 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6396 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6397 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6398 address = if index then offset_addr else R[n];
6399 data = MemU[address,2];
6400 if wback then R[n] = offset_addr;
6401 if UnalignedSupport() || address<0> = ’0’ then
6402 R[t] = ZeroExtend(data, 32);
6403 else // Can only apply before ARMv7
6404 R[t] = bits(32) UNKNOWN;
6405#endif
6406
6407 bool success = false;
6408 const uint32_t opcode = OpcodeAsUnsigned (&success);
6409 if (!success)
6410 return false;
6411
6412 if (ConditionPassed())
6413 {
6414 uint32_t t;
6415 uint32_t n;
6416 uint32_t m;
6417 bool index;
6418 bool add;
6419 bool wback;
6420 ARM_ShifterType shift_t;
6421 uint32_t shift_n;
6422
6423 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6424 switch (encoding)
6425 {
6426 case eEncodingT1:
6427 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6428 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6429 t = Bits32 (opcode, 2, 0);
6430 n = Bits32 (opcode, 5, 3);
6431 m = Bits32 (opcode, 8, 6);
6432
6433 // index = TRUE; add = TRUE; wback = FALSE;
6434 index = true;
6435 add = true;
6436 wback = false;
6437
6438 // (shift_t, shift_n) = (SRType_LSL, 0);
6439 shift_t = SRType_LSL;
6440 shift_n = 0;
6441
6442 break;
6443
6444 case eEncodingT2:
6445 // if Rn == ’1111’ then SEE LDRH (literal);
6446 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6447 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6448 t = Bits32 (opcode, 15, 12);
6449 n = Bits32 (opcode, 19, 16);
6450 m = Bits32 (opcode, 3, 0);
6451
6452 // index = TRUE; add = TRUE; wback = FALSE;
6453 index = true;
6454 add = true;
6455 wback = false;
6456
6457 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6458 shift_t = SRType_LSL;
6459 shift_n = Bits32 (opcode, 5, 4);
6460
6461 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6462 if ((t == 13) || BadReg (m))
6463 return false;
6464 break;
6465
6466 case eEncodingA1:
6467 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6468 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6469 t = Bits32 (opcode, 15, 12);
6470 n = Bits32 (opcode, 19, 16);
6471 m = Bits32 (opcode, 3, 0);
6472
6473 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6474 index = BitIsSet (opcode, 24);
6475 add = BitIsSet (opcode, 23);
6476 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6477
6478 // (shift_t, shift_n) = (SRType_LSL, 0);
6479 shift_t = SRType_LSL;
6480 shift_n = 0;
6481
6482 // if t == 15 || m == 15 then UNPREDICTABLE;
6483 if ((t == 15) || (m == 15))
6484 return false;
6485
6486 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6487 if (wback && ((n == 15) || (n == t)))
6488 return false;
6489
6490 break;
6491
6492 default:
6493 return false;
6494 }
6495
6496 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6497
6498 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6499 if (!success)
6500 return false;
6501
6502 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6503
6504 addr_t offset_addr;
6505 addr_t address;
6506
6507 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6508 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6509 if (!success)
6510 return false;
6511
6512 if (add)
6513 offset_addr = Rn + offset;
6514 else
6515 offset_addr = Rn - offset;
6516
6517 // address = if index then offset_addr else R[n];
6518 if (index)
6519 address = offset_addr;
6520 else
6521 address = Rn;
6522
6523 // data = MemU[address,2];
6524 Register base_reg;
6525 Register offset_reg;
6526 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6527 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6528
6529 EmulateInstruction::Context context;
6530 context.type = eContextRegisterLoad;
6531 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6532 uint64_t data = MemURead (context, address, 2, 0, &success);
6533 if (!success)
6534 return false;
6535
6536 // if wback then R[n] = offset_addr;
6537 if (wback)
6538 {
6539 context.type = eContextAdjustBaseRegister;
6540 context.SetAddress (offset_addr);
6541 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6542 return false;
6543 }
6544
6545 // if UnalignedSupport() || address<0> = ’0’ then
6546 if (UnalignedSupport() || BitIsClear (address, 0))
6547 {
6548 // R[t] = ZeroExtend(data, 32);
6549 context.type = eContextRegisterLoad;
6550 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6551 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6552 return false;
6553 }
6554 else // Can only apply before ARMv7
6555 {
6556 // R[t] = bits(32) UNKNOWN;
6557 WriteBits32Unknown (t);
6558 }
6559 }
6560 return true;
6561}
6562
Caroline Ticea5e28af2011-03-01 21:53:03 +00006563// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6564// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6565// or pre-indexed addressing.
6566bool
6567EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6568{
6569#if 0
6570 if ConditionPassed() then
6571 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6572 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6573 address = if index then offset_addr else R[n];
6574 R[t] = SignExtend(MemU[address,1], 32);
6575 if wback then R[n] = offset_addr;
6576#endif
6577
6578 bool success = false;
6579 const uint32_t opcode = OpcodeAsUnsigned (&success);
6580 if (!success)
6581 return false;
6582
6583 if (ConditionPassed ())
6584 {
6585 uint32_t t;
6586 uint32_t n;
6587 uint32_t imm32;
6588 bool index;
6589 bool add;
6590 bool wback;
6591
6592 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6593 switch (encoding)
6594 {
6595 case eEncodingT1:
6596 // if Rt == ’1111’ then SEE PLI;
6597 // if Rn == ’1111’ then SEE LDRSB (literal);
6598 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6599 t = Bits32 (opcode, 15, 12);
6600 n = Bits32 (opcode, 19, 16);
6601 imm32 = Bits32 (opcode, 11, 0);
6602
6603 // index = TRUE; add = TRUE; wback = FALSE;
6604 index = true;
6605 add = true;
6606 wback = false;
6607
6608 // if t == 13 then UNPREDICTABLE;
6609 if (t == 13)
6610 return false;
6611
6612 break;
6613
6614 case eEncodingT2:
6615 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6616 // if Rn == ’1111’ then SEE LDRSB (literal);
6617 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6618 // if P == ’0’ && W == ’0’ then UNDEFINED;
6619 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6620 return false;
6621
6622 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6623 t = Bits32 (opcode, 15, 12);
6624 n = Bits32 (opcode, 19, 16);
6625 imm32 = Bits32 (opcode, 7, 0);
6626
6627 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6628 index = BitIsSet (opcode, 10);
6629 add = BitIsSet (opcode, 9);
6630 wback = BitIsSet (opcode, 8);
6631
6632 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6633 if (BadReg (t) || (wback && (n == t)))
6634 return false;
6635
6636 break;
6637
6638 case eEncodingA1:
6639 {
6640 // if Rn == ’1111’ then SEE LDRSB (literal);
6641 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6642 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6643 t = Bits32 (opcode, 15, 12);
6644 n = Bits32 (opcode, 19, 16);
6645
6646 uint32_t imm4H = Bits32 (opcode, 11, 8);
6647 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006648 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006649
6650 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6651 index = BitIsSet (opcode, 24);
6652 add = BitIsSet (opcode, 23);
6653 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6654
6655 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6656 if ((t == 15) || (wback && (n == t)))
6657 return false;
6658
6659 break;
6660 }
6661
6662 default:
6663 return false;
6664 }
6665
6666 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6667 if (!success)
6668 return false;
6669
6670 addr_t offset_addr;
6671 addr_t address;
6672
6673 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6674 if (add)
6675 offset_addr = Rn + imm32;
6676 else
6677 offset_addr = Rn - imm32;
6678
6679 // address = if index then offset_addr else R[n];
6680 if (index)
6681 address = offset_addr;
6682 else
6683 address = Rn;
6684
6685 // R[t] = SignExtend(MemU[address,1], 32);
6686 Register base_reg;
6687 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6688
6689 EmulateInstruction::Context context;
6690 context.type = eContextRegisterLoad;
6691 context.SetRegisterPlusOffset (base_reg, address - Rn);
6692
6693 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6694 if (!success)
6695 return false;
6696
6697 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6699 return false;
6700
6701 // if wback then R[n] = offset_addr;
6702 if (wback)
6703 {
6704 context.type = eContextAdjustBaseRegister;
6705 context.SetAddress (offset_addr);
6706 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6707 return false;
6708 }
6709 }
6710
6711 return true;
6712}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006713
Caroline Tice5f593912011-03-01 22:25:17 +00006714// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6715// sign-extends it to form a 32-bit word, and writes tit to a register.
6716bool
6717EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6718{
6719#if 0
6720 if ConditionPassed() then
6721 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6722 base = Align(PC,4);
6723 address = if add then (base + imm32) else (base - imm32);
6724 R[t] = SignExtend(MemU[address,1], 32);
6725#endif
6726
6727 bool success = false;
6728 const uint32_t opcode = OpcodeAsUnsigned (&success);
6729 if (!success)
6730 return false;
6731
6732 if (ConditionPassed ())
6733 {
6734 uint32_t t;
6735 uint32_t imm32;
6736 bool add;
6737
6738 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6739 switch (encoding)
6740 {
6741 case eEncodingT1:
6742 // if Rt == ’1111’ then SEE PLI;
6743 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6744 t = Bits32 (opcode, 15, 12);
6745 imm32 = Bits32 (opcode, 11, 0);
6746 add = BitIsSet (opcode, 23);
6747
6748 // if t == 13 then UNPREDICTABLE;
6749 if (t == 13)
6750 return false;
6751
6752 break;
6753
6754 case eEncodingA1:
6755 {
6756 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6757 t = Bits32 (opcode, 15, 12);
6758 uint32_t imm4H = Bits32 (opcode, 11, 8);
6759 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006760 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006761 add = BitIsSet (opcode, 23);
6762
6763 // if t == 15 then UNPREDICTABLE;
6764 if (t == 15)
6765 return false;
6766
6767 break;
6768 }
6769
6770 default:
6771 return false;
6772 }
6773
6774 // base = Align(PC,4);
6775 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6776 &success);
6777 if (!success)
6778 return false;
6779 uint64_t base = AlignPC (pc_value);
6780
6781 // address = if add then (base + imm32) else (base - imm32);
6782 addr_t address;
6783 if (add)
6784 address = base + imm32;
6785 else
6786 address = base - imm32;
6787
6788 // R[t] = SignExtend(MemU[address,1], 32);
6789 Register base_reg;
6790 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6791
6792 EmulateInstruction::Context context;
6793 context.type = eContextRegisterLoad;
6794 context.SetRegisterPlusOffset (base_reg, address - base);
6795
6796 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6797 if (!success)
6798 return false;
6799
6800 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6801 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6802 return false;
6803 }
6804 return true;
6805}
6806
Caroline Tice672f3112011-03-01 23:55:59 +00006807// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6808// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6809// shifted left by 0, 1, 2, or 3 bits.
6810bool
6811EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
6812{
6813#if 0
6814 if ConditionPassed() then
6815 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6816 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6817 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6818 address = if index then offset_addr else R[n];
6819 R[t] = SignExtend(MemU[address,1], 32);
6820 if wback then R[n] = offset_addr;
6821#endif
6822
6823 bool success = false;
6824 const uint32_t opcode = OpcodeAsUnsigned (&success);
6825 if (!success)
6826 return false;
6827
6828 if (ConditionPassed ())
6829 {
6830 uint32_t t;
6831 uint32_t n;
6832 uint32_t m;
6833 bool index;
6834 bool add;
6835 bool wback;
6836 ARM_ShifterType shift_t;
6837 uint32_t shift_n;
6838
6839 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6840 switch (encoding)
6841 {
6842 case eEncodingT1:
6843 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6844 t = Bits32 (opcode, 2, 0);
6845 n = Bits32 (opcode, 5, 3);
6846 m = Bits32 (opcode, 8, 6);
6847
6848 // index = TRUE; add = TRUE; wback = FALSE;
6849 index = true;
6850 add = true;
6851 wback = false;
6852
6853 // (shift_t, shift_n) = (SRType_LSL, 0);
6854 shift_t = SRType_LSL;
6855 shift_n = 0;
6856
6857 break;
6858
6859 case eEncodingT2:
6860 // if Rt == ’1111’ then SEE PLI;
6861 // if Rn == ’1111’ then SEE LDRSB (literal);
6862 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6863 t = Bits32 (opcode, 15, 12);
6864 n = Bits32 (opcode, 19, 16);
6865 m = Bits32 (opcode, 3, 0);
6866
6867 // index = TRUE; add = TRUE; wback = FALSE;
6868 index = true;
6869 add = true;
6870 wback = false;
6871
6872 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6873 shift_t = SRType_LSL;
6874 shift_n = Bits32 (opcode, 5, 4);
6875
6876 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6877 if ((t == 13) || BadReg (m))
6878 return false;
6879 break;
6880
6881 case eEncodingA1:
6882 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6883 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6884 t = Bits32 (opcode, 15, 12);
6885 n = Bits32 (opcode, 19, 16);
6886 m = Bits32 (opcode, 3, 0);
6887
6888 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6889 index = BitIsSet (opcode, 24);
6890 add = BitIsSet (opcode, 23);
6891 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6892
6893 // (shift_t, shift_n) = (SRType_LSL, 0);
6894 shift_t = SRType_LSL;
6895 shift_n = 0;
6896
6897 // if t == 15 || m == 15 then UNPREDICTABLE;
6898 if ((t == 15) || (m == 15))
6899 return false;
6900
6901 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6902 if (wback && ((n == 15) || (n == t)))
6903 return false;
6904 break;
6905
6906 default:
6907 return false;
6908 }
6909
6910 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6911 if (!success)
6912 return false;
6913
6914 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6915 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6916
6917 addr_t offset_addr;
6918 addr_t address;
6919
6920 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6921 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6922 if (!success)
6923 return false;
6924
6925 if (add)
6926 offset_addr = Rn + offset;
6927 else
6928 offset_addr = Rn - offset;
6929
6930 // address = if index then offset_addr else R[n];
6931 if (index)
6932 address = offset_addr;
6933 else
6934 address = Rn;
6935
6936 // R[t] = SignExtend(MemU[address,1], 32);
6937 Register base_reg;
6938 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6939 Register offset_reg;
6940 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6941
6942 EmulateInstruction::Context context;
6943 context.type = eContextRegisterLoad;
6944 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6945
6946 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6947 if (!success)
6948 return false;
6949
6950 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6951 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6952 return false;
6953
6954 // if wback then R[n] = offset_addr;
6955 if (wback)
6956 {
6957 context.type = eContextAdjustBaseRegister;
6958 context.SetAddress (offset_addr);
6959 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6960 return false;
6961 }
6962 }
6963 return true;
6964}
6965
Caroline Tice78fb5632011-03-02 00:39:42 +00006966// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
6967// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
6968// pre-indexed addressing.
6969bool
6970EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
6971{
6972#if 0
6973 if ConditionPassed() then
6974 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6975 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6976 address = if index then offset_addr else R[n];
6977 data = MemU[address,2];
6978 if wback then R[n] = offset_addr;
6979 if UnalignedSupport() || address<0> = ’0’ then
6980 R[t] = SignExtend(data, 32);
6981 else // Can only apply before ARMv7
6982 R[t] = bits(32) UNKNOWN;
6983#endif
6984
6985 bool success = false;
6986 const uint32_t opcode = OpcodeAsUnsigned (&success);
6987 if (!success)
6988 return false;
6989
6990 if (ConditionPassed())
6991 {
6992 uint32_t t;
6993 uint32_t n;
6994 uint32_t imm32;
6995 bool index;
6996 bool add;
6997 bool wback;
6998
6999 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7000 switch (encoding)
7001 {
7002 case eEncodingT1:
7003 // if Rn == ’1111’ then SEE LDRSH (literal);
7004 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7005 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7006 t = Bits32 (opcode, 15, 12);
7007 n = Bits32 (opcode, 19, 16);
7008 imm32 = Bits32 (opcode, 11, 0);
7009
7010 // index = TRUE; add = TRUE; wback = FALSE;
7011 index = true;
7012 add = true;
7013 wback = false;
7014
7015 // if t == 13 then UNPREDICTABLE;
7016 if (t == 13)
7017 return false;
7018
7019 break;
7020
7021 case eEncodingT2:
7022 // if Rn == ’1111’ then SEE LDRSH (literal);
7023 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7024 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7025 // if P == ’0’ && W == ’0’ then UNDEFINED;
7026 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7027 return false;
7028
7029 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7030 t = Bits32 (opcode, 15, 12);
7031 n = Bits32 (opcode, 19, 16);
7032 imm32 = Bits32 (opcode, 7, 0);
7033
7034 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7035 index = BitIsSet (opcode, 10);
7036 add = BitIsSet (opcode, 9);
7037 wback = BitIsSet (opcode, 8);
7038
7039 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7040 if (BadReg (t) || (wback && (n == t)))
7041 return false;
7042
7043 break;
7044
7045 case eEncodingA1:
7046 {
7047 // if Rn == ’1111’ then SEE LDRSH (literal);
7048 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7049 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7050 t = Bits32 (opcode, 15, 12);
7051 n = Bits32 (opcode, 19, 16);
7052 uint32_t imm4H = Bits32 (opcode, 11,8);
7053 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007054 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007055
7056 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7057 index = BitIsSet (opcode, 24);
7058 add = BitIsSet (opcode, 23);
7059 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7060
7061 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7062 if ((t == 15) || (wback && (n == t)))
7063 return false;
7064
7065 break;
7066 }
7067
7068 default:
7069 return false;
7070 }
7071
7072 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7073 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7074 if (!success)
7075 return false;
7076
7077 addr_t offset_addr;
7078 if (add)
7079 offset_addr = Rn + imm32;
7080 else
7081 offset_addr = Rn - imm32;
7082
7083 // address = if index then offset_addr else R[n];
7084 addr_t address;
7085 if (index)
7086 address = offset_addr;
7087 else
7088 address = Rn;
7089
7090 // data = MemU[address,2];
7091 Register base_reg;
7092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7093
7094 EmulateInstruction::Context context;
7095 context.type = eContextRegisterLoad;
7096 context.SetRegisterPlusOffset (base_reg, address - Rn);
7097
7098 uint64_t data = MemURead (context, address, 2, 0, &success);
7099 if (!success)
7100 return false;
7101
7102 // if wback then R[n] = offset_addr;
7103 if (wback)
7104 {
7105 context.type = eContextAdjustBaseRegister;
7106 context.SetAddress (offset_addr);
7107 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7108 return false;
7109 }
7110
7111 // if UnalignedSupport() || address<0> = ’0’ then
7112 if (UnalignedSupport() || BitIsClear (address, 0))
7113 {
7114 // R[t] = SignExtend(data, 32);
7115 int64_t signed_data = llvm::SignExtend64<16>(data);
7116 context.type = eContextRegisterLoad;
7117 context.SetRegisterPlusOffset (base_reg, address - Rn);
7118 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7119 return false;
7120 }
7121 else // Can only apply before ARMv7
7122 {
7123 // R[t] = bits(32) UNKNOWN;
7124 WriteBits32Unknown (t);
7125 }
7126 }
7127 return true;
7128}
7129
Caroline Ticed2fac092011-03-02 19:45:34 +00007130// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7131// sign-extends it to from a 32-bit word, and writes it to a register.
7132bool
7133EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7134{
7135#if 0
7136 if ConditionPassed() then
7137 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7138 base = Align(PC,4);
7139 address = if add then (base + imm32) else (base - imm32);
7140 data = MemU[address,2];
7141 if UnalignedSupport() || address<0> = ’0’ then
7142 R[t] = SignExtend(data, 32);
7143 else // Can only apply before ARMv7
7144 R[t] = bits(32) UNKNOWN;
7145#endif
7146
7147 bool success = false;
7148 const uint32_t opcode = OpcodeAsUnsigned (&success);
7149 if (!success)
7150 return false;
7151
7152 if (ConditionPassed())
7153 {
7154 uint32_t t;
7155 uint32_t imm32;
7156 bool add;
7157
7158 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7159 switch (encoding)
7160 {
7161 case eEncodingT1:
7162 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7163 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7164 t = Bits32 (opcode, 15, 12);
7165 imm32 = Bits32 (opcode, 11, 0);
7166 add = BitIsSet (opcode, 23);
7167
7168 // if t == 13 then UNPREDICTABLE;
7169 if (t == 13)
7170 return false;
7171
7172 break;
7173
7174 case eEncodingA1:
7175 {
7176 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7177 t = Bits32 (opcode, 15, 12);
7178 uint32_t imm4H = Bits32 (opcode, 11, 8);
7179 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007180 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007181 add = BitIsSet (opcode, 23);
7182
7183 // if t == 15 then UNPREDICTABLE;
7184 if (t == 15)
7185 return false;
7186
7187 break;
7188 }
7189 default:
7190 return false;
7191 }
7192
7193 // base = Align(PC,4);
7194 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
7195 if (!success)
7196 return false;
7197
7198 uint64_t base = AlignPC (pc_value);
7199
7200 addr_t address;
7201 // address = if add then (base + imm32) else (base - imm32);
7202 if (add)
7203 address = base + imm32;
7204 else
7205 address = base - imm32;
7206
7207 // data = MemU[address,2];
7208 Register base_reg;
7209 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7210
7211 EmulateInstruction::Context context;
7212 context.type = eContextRegisterLoad;
7213 context.SetRegisterPlusOffset (base_reg, imm32);
7214
7215 uint64_t data = MemURead (context, address, 2, 0, &success);
7216 if (!success)
7217 return false;
7218
7219 // if UnalignedSupport() || address<0> = ’0’ then
7220 if (UnalignedSupport() || BitIsClear (address, 0))
7221 {
7222 // R[t] = SignExtend(data, 32);
7223 int64_t signed_data = llvm::SignExtend64<16>(data);
7224 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7225 return false;
7226 }
7227 else // Can only apply before ARMv7
7228 {
7229 // R[t] = bits(32) UNKNOWN;
7230 WriteBits32Unknown (t);
7231 }
7232 }
7233 return true;
7234}
7235
Caroline Tice291a3e92011-03-02 21:13:44 +00007236// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7237// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7238// shifted left by 0, 1, 2, or 3 bits.
7239bool
7240EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7241{
7242#if 0
7243 if ConditionPassed() then
7244 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7245 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7246 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7247 address = if index then offset_addr else R[n];
7248 data = MemU[address,2];
7249 if wback then R[n] = offset_addr;
7250 if UnalignedSupport() || address<0> = ’0’ then
7251 R[t] = SignExtend(data, 32);
7252 else // Can only apply before ARMv7
7253 R[t] = bits(32) UNKNOWN;
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 t;
7264 uint32_t n;
7265 uint32_t m;
7266 bool index;
7267 bool add;
7268 bool wback;
7269 ARM_ShifterType shift_t;
7270 uint32_t shift_n;
7271
7272 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7273 switch (encoding)
7274 {
7275 case eEncodingT1:
7276 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7277 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7278 t = Bits32 (opcode, 2, 0);
7279 n = Bits32 (opcode, 5, 3);
7280 m = Bits32 (opcode, 8, 6);
7281
7282 // index = TRUE; add = TRUE; wback = FALSE;
7283 index = true;
7284 add = true;
7285 wback = false;
7286
7287 // (shift_t, shift_n) = (SRType_LSL, 0);
7288 shift_t = SRType_LSL;
7289 shift_n = 0;
7290
7291 break;
7292
7293 case eEncodingT2:
7294 // if Rn == ’1111’ then SEE LDRSH (literal);
7295 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7296 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7297 t = Bits32 (opcode, 15, 12);
7298 n = Bits32 (opcode, 19, 16);
7299 m = Bits32 (opcode, 3, 0);
7300
7301 // index = TRUE; add = TRUE; wback = FALSE;
7302 index = true;
7303 add = true;
7304 wback = false;
7305
7306 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7307 shift_t = SRType_LSL;
7308 shift_n = Bits32 (opcode, 5, 4);
7309
7310 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7311 if ((t == 13) || BadReg (m))
7312 return false;
7313
7314 break;
7315
7316 case eEncodingA1:
7317 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7318 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7319 t = Bits32 (opcode, 15, 12);
7320 n = Bits32 (opcode, 19, 16);
7321 m = Bits32 (opcode, 3, 0);
7322
7323 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7324 index = BitIsSet (opcode, 24);
7325 add = BitIsSet (opcode, 23);
7326 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7327
7328 // (shift_t, shift_n) = (SRType_LSL, 0);
7329 shift_t = SRType_LSL;
7330 shift_n = 0;
7331
7332 // if t == 15 || m == 15 then UNPREDICTABLE;
7333 if ((t == 15) || (m == 15))
7334 return false;
7335
7336 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7337 if (wback && ((n == 15) || (n == t)))
7338 return false;
7339
7340 break;
7341
7342 default:
7343 break;
7344 }
7345
7346 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7347 if (!success)
7348 return false;
7349
7350 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7351 if (!success)
7352 return false;
7353
7354 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7355 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7356
7357 addr_t offset_addr;
7358 addr_t address;
7359
7360 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7361 if (add)
7362 offset_addr = Rn + offset;
7363 else
7364 offset_addr = Rn - offset;
7365
7366 // address = if index then offset_addr else R[n];
7367 if (index)
7368 address = offset_addr;
7369 else
7370 address = Rn;
7371
7372 // data = MemU[address,2];
7373 Register base_reg;
7374 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7375
7376 Register offset_reg;
7377 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7378
7379 EmulateInstruction::Context context;
7380 context.type = eContextRegisterLoad;
7381 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7382
7383 uint64_t data = MemURead (context, address, 2, 0, &success);
7384 if (!success)
7385 return false;
7386
7387 // if wback then R[n] = offset_addr;
7388 if (wback)
7389 {
7390 context.type = eContextAdjustBaseRegister;
7391 context.SetAddress (offset_addr);
7392 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7393 return false;
7394 }
7395
7396 // if UnalignedSupport() || address<0> = ’0’ then
7397 if (UnalignedSupport() || BitIsClear (address, 0))
7398 {
7399 // R[t] = SignExtend(data, 32);
7400 context.type = eContextRegisterLoad;
7401 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7402
7403 int64_t signed_data = llvm::SignExtend64<16>(data);
7404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7405 return false;
7406 }
7407 else // Can only apply before ARMv7
7408 {
7409 // R[t] = bits(32) UNKNOWN;
7410 WriteBits32Unknown (t);
7411 }
7412 }
7413 return true;
7414}
7415
Johnny Chen2115b412011-02-21 23:42:44 +00007416// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7417// and writes the result to the destination register. It can optionally update the condition flags based on
7418// the result.
7419bool
7420EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
7421{
7422#if 0
7423 // ARM pseudo code...
7424 if ConditionPassed() then
7425 EncodingSpecificOperations();
7426 result = R[n] EOR imm32;
7427 if d == 15 then // Can only occur for ARM encoding
7428 ALUWritePC(result); // setflags is always FALSE here
7429 else
7430 R[d] = result;
7431 if setflags then
7432 APSR.N = result<31>;
7433 APSR.Z = IsZeroBit(result);
7434 APSR.C = carry;
7435 // APSR.V unchanged
7436#endif
7437
7438 bool success = false;
7439 const uint32_t opcode = OpcodeAsUnsigned (&success);
7440 if (!success)
7441 return false;
7442
7443 if (ConditionPassed())
7444 {
7445 uint32_t Rd, Rn;
7446 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7447 bool setflags;
7448 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7449 switch (encoding)
7450 {
7451 case eEncodingT1:
7452 Rd = Bits32(opcode, 11, 8);
7453 Rn = Bits32(opcode, 19, 16);
7454 setflags = BitIsSet(opcode, 20);
7455 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7456 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7457 if (Rd == 15 && setflags)
7458 return EmulateTEQImm(eEncodingT1);
7459 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7460 return false;
7461 break;
7462 case eEncodingA1:
7463 Rd = Bits32(opcode, 15, 12);
7464 Rn = Bits32(opcode, 19, 16);
7465 setflags = BitIsSet(opcode, 20);
7466 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7467 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7468 // TODO: Emulate SUBS PC, LR and related instructions.
7469 if (Rd == 15 && setflags)
7470 return false;
7471 break;
7472 default:
7473 return false;
7474 }
7475
7476 // Read the first operand.
7477 uint32_t val1 = ReadCoreReg(Rn, &success);
7478 if (!success)
7479 return false;
7480
7481 uint32_t result = val1 ^ imm32;
7482
7483 EmulateInstruction::Context context;
7484 context.type = EmulateInstruction::eContextImmediate;
7485 context.SetNoArgs ();
7486
7487 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7488 return false;
7489 }
7490 return true;
7491}
7492
7493// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7494// optionally-shifted register value, and writes the result to the destination register.
7495// It can optionally update the condition flags based on the result.
7496bool
7497EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7498{
7499#if 0
7500 // ARM pseudo code...
7501 if ConditionPassed() then
7502 EncodingSpecificOperations();
7503 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7504 result = R[n] EOR shifted;
7505 if d == 15 then // Can only occur for ARM encoding
7506 ALUWritePC(result); // setflags is always FALSE here
7507 else
7508 R[d] = result;
7509 if setflags then
7510 APSR.N = result<31>;
7511 APSR.Z = IsZeroBit(result);
7512 APSR.C = carry;
7513 // APSR.V unchanged
7514#endif
7515
7516 bool success = false;
7517 const uint32_t opcode = OpcodeAsUnsigned (&success);
7518 if (!success)
7519 return false;
7520
7521 if (ConditionPassed())
7522 {
7523 uint32_t Rd, Rn, Rm;
7524 ARM_ShifterType shift_t;
7525 uint32_t shift_n; // the shift applied to the value read from Rm
7526 bool setflags;
7527 uint32_t carry;
7528 switch (encoding)
7529 {
7530 case eEncodingT1:
7531 Rd = Rn = Bits32(opcode, 2, 0);
7532 Rm = Bits32(opcode, 5, 3);
7533 setflags = !InITBlock();
7534 shift_t = SRType_LSL;
7535 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007536 break;
Johnny Chen2115b412011-02-21 23:42:44 +00007537 case eEncodingT2:
7538 Rd = Bits32(opcode, 11, 8);
7539 Rn = Bits32(opcode, 19, 16);
7540 Rm = Bits32(opcode, 3, 0);
7541 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007542 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7543 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00007544 if (Rd == 15 && setflags)
7545 return EmulateTEQReg(eEncodingT1);
7546 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
7547 return false;
7548 break;
7549 case eEncodingA1:
7550 Rd = Bits32(opcode, 15, 12);
7551 Rn = Bits32(opcode, 19, 16);
7552 Rm = Bits32(opcode, 3, 0);
7553 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007554 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007555 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7556 // TODO: Emulate SUBS PC, LR and related instructions.
7557 if (Rd == 15 && setflags)
7558 return false;
7559 break;
7560 default:
7561 return false;
7562 }
7563
7564 // Read the first operand.
7565 uint32_t val1 = ReadCoreReg(Rn, &success);
7566 if (!success)
7567 return false;
7568
7569 // Read the second operand.
7570 uint32_t val2 = ReadCoreReg(Rm, &success);
7571 if (!success)
7572 return false;
7573
7574 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7575 uint32_t result = val1 ^ shifted;
7576
7577 EmulateInstruction::Context context;
7578 context.type = EmulateInstruction::eContextImmediate;
7579 context.SetNoArgs ();
7580
7581 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7582 return false;
7583 }
7584 return true;
7585}
7586
Johnny Chen7c5234d2011-02-18 23:41:11 +00007587// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
7588// writes the result to the destination register. It can optionally update the condition flags based
7589// on the result.
7590bool
7591EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
7592{
7593#if 0
7594 // ARM pseudo code...
7595 if ConditionPassed() then
7596 EncodingSpecificOperations();
7597 result = R[n] OR imm32;
7598 if d == 15 then // Can only occur for ARM encoding
7599 ALUWritePC(result); // setflags is always FALSE here
7600 else
7601 R[d] = result;
7602 if setflags then
7603 APSR.N = result<31>;
7604 APSR.Z = IsZeroBit(result);
7605 APSR.C = carry;
7606 // APSR.V unchanged
7607#endif
7608
7609 bool success = false;
7610 const uint32_t opcode = OpcodeAsUnsigned (&success);
7611 if (!success)
7612 return false;
7613
7614 if (ConditionPassed())
7615 {
7616 uint32_t Rd, Rn;
7617 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7618 bool setflags;
7619 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7620 switch (encoding)
7621 {
7622 case eEncodingT1:
7623 Rd = Bits32(opcode, 11, 8);
7624 Rn = Bits32(opcode, 19, 16);
7625 setflags = BitIsSet(opcode, 20);
7626 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7627 // if Rn == ‘1111’ then SEE MOV (immediate);
7628 if (Rn == 15)
7629 return EmulateMOVRdImm(eEncodingT2);
7630 if (BadReg(Rd) || Rn == 13)
7631 return false;
7632 break;
7633 case eEncodingA1:
7634 Rd = Bits32(opcode, 15, 12);
7635 Rn = Bits32(opcode, 19, 16);
7636 setflags = BitIsSet(opcode, 20);
7637 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7638 // TODO: Emulate SUBS PC, LR and related instructions.
7639 if (Rd == 15 && setflags)
7640 return false;
7641 break;
7642 default:
7643 return false;
7644 }
7645
7646 // Read the first operand.
7647 uint32_t val1 = ReadCoreReg(Rn, &success);
7648 if (!success)
7649 return false;
7650
7651 uint32_t result = val1 | imm32;
7652
7653 EmulateInstruction::Context context;
7654 context.type = EmulateInstruction::eContextImmediate;
7655 context.SetNoArgs ();
7656
7657 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7658 return false;
7659 }
7660 return true;
7661}
7662
7663// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
7664// value, and writes the result to the destination register. It can optionally update the condition flags based
7665// on the result.
7666bool
7667EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
7668{
7669#if 0
7670 // ARM pseudo code...
7671 if ConditionPassed() then
7672 EncodingSpecificOperations();
7673 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7674 result = R[n] OR shifted;
7675 if d == 15 then // Can only occur for ARM encoding
7676 ALUWritePC(result); // setflags is always FALSE here
7677 else
7678 R[d] = result;
7679 if setflags then
7680 APSR.N = result<31>;
7681 APSR.Z = IsZeroBit(result);
7682 APSR.C = carry;
7683 // APSR.V unchanged
7684#endif
7685
7686 bool success = false;
7687 const uint32_t opcode = OpcodeAsUnsigned (&success);
7688 if (!success)
7689 return false;
7690
7691 if (ConditionPassed())
7692 {
7693 uint32_t Rd, Rn, Rm;
7694 ARM_ShifterType shift_t;
7695 uint32_t shift_n; // the shift applied to the value read from Rm
7696 bool setflags;
7697 uint32_t carry;
7698 switch (encoding)
7699 {
7700 case eEncodingT1:
7701 Rd = Rn = Bits32(opcode, 2, 0);
7702 Rm = Bits32(opcode, 5, 3);
7703 setflags = !InITBlock();
7704 shift_t = SRType_LSL;
7705 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007706 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007707 case eEncodingT2:
7708 Rd = Bits32(opcode, 11, 8);
7709 Rn = Bits32(opcode, 19, 16);
7710 Rm = Bits32(opcode, 3, 0);
7711 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007712 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7713 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007714 if (Rn == 15)
7715 return EmulateMOVRdRm(eEncodingT3);
7716 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
7717 return false;
7718 break;
7719 case eEncodingA1:
7720 Rd = Bits32(opcode, 15, 12);
7721 Rn = Bits32(opcode, 19, 16);
7722 Rm = Bits32(opcode, 3, 0);
7723 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007724 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007725 // TODO: Emulate SUBS PC, LR and related instructions.
7726 if (Rd == 15 && setflags)
7727 return false;
7728 break;
7729 default:
7730 return false;
7731 }
7732
7733 // Read the first operand.
7734 uint32_t val1 = ReadCoreReg(Rn, &success);
7735 if (!success)
7736 return false;
7737
7738 // Read the second operand.
7739 uint32_t val2 = ReadCoreReg(Rm, &success);
7740 if (!success)
7741 return false;
7742
7743 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00007744 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007745
7746 EmulateInstruction::Context context;
7747 context.type = EmulateInstruction::eContextImmediate;
7748 context.SetNoArgs ();
7749
7750 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7751 return false;
7752 }
7753 return true;
7754}
7755
Johnny Chened32e7c2011-02-22 23:42:58 +00007756// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
7757// the destination register. It can optionally update the condition flags based on the result.
7758bool
7759EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
7760{
7761#if 0
7762 // ARM pseudo code...
7763 if ConditionPassed() then
7764 EncodingSpecificOperations();
7765 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
7766 if d == 15 then // Can only occur for ARM encoding
7767 ALUWritePC(result); // setflags is always FALSE here
7768 else
7769 R[d] = result;
7770 if setflags then
7771 APSR.N = result<31>;
7772 APSR.Z = IsZeroBit(result);
7773 APSR.C = carry;
7774 APSR.V = overflow;
7775#endif
7776
7777 bool success = false;
7778 const uint32_t opcode = OpcodeAsUnsigned (&success);
7779 if (!success)
7780 return false;
7781
7782 uint32_t Rd; // the destination register
7783 uint32_t Rn; // the first operand
7784 bool setflags;
7785 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7786 switch (encoding) {
7787 case eEncodingT1:
7788 Rd = Bits32(opcode, 2, 0);
7789 Rn = Bits32(opcode, 5, 3);
7790 setflags = !InITBlock();
7791 imm32 = 0;
7792 break;
7793 case eEncodingT2:
7794 Rd = Bits32(opcode, 11, 8);
7795 Rn = Bits32(opcode, 19, 16);
7796 setflags = BitIsSet(opcode, 20);
7797 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7798 if (BadReg(Rd) || BadReg(Rn))
7799 return false;
7800 break;
7801 case eEncodingA1:
7802 Rd = Bits32(opcode, 15, 12);
7803 Rn = Bits32(opcode, 19, 16);
7804 setflags = BitIsSet(opcode, 20);
7805 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7806 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7807 // TODO: Emulate SUBS PC, LR and related instructions.
7808 if (Rd == 15 && setflags)
7809 return false;
7810 break;
7811 default:
7812 return false;
7813 }
7814 // Read the register value from the operand register Rn.
7815 uint32_t reg_val = ReadCoreReg(Rn, &success);
7816 if (!success)
7817 return false;
7818
7819 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
7820
7821 EmulateInstruction::Context context;
7822 context.type = EmulateInstruction::eContextImmediate;
7823 context.SetNoArgs ();
7824
7825 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7826 return false;
7827
7828 return true;
7829}
7830
7831// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
7832// result to the destination register. It can optionally update the condition flags based on the result.
7833bool
7834EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
7835{
7836#if 0
7837 // ARM pseudo code...
7838 if ConditionPassed() then
7839 EncodingSpecificOperations();
7840 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7841 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
7842 if d == 15 then // Can only occur for ARM encoding
7843 ALUWritePC(result); // setflags is always FALSE here
7844 else
7845 R[d] = result;
7846 if setflags then
7847 APSR.N = result<31>;
7848 APSR.Z = IsZeroBit(result);
7849 APSR.C = carry;
7850 APSR.V = overflow;
7851#endif
7852
7853 bool success = false;
7854 const uint32_t opcode = OpcodeAsUnsigned (&success);
7855 if (!success)
7856 return false;
7857
7858 uint32_t Rd; // the destination register
7859 uint32_t Rn; // the first operand
7860 uint32_t Rm; // the second operand
7861 bool setflags;
7862 ARM_ShifterType shift_t;
7863 uint32_t shift_n; // the shift applied to the value read from Rm
7864 switch (encoding) {
7865 case eEncodingT1:
7866 Rd = Bits32(opcode, 11, 8);
7867 Rn = Bits32(opcode, 19, 16);
7868 Rm = Bits32(opcode, 3, 0);
7869 setflags = BitIsSet(opcode, 20);
7870 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7871 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
7872 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
7873 return false;
7874 break;
7875 case eEncodingA1:
7876 Rd = Bits32(opcode, 15, 12);
7877 Rn = Bits32(opcode, 19, 16);
7878 Rm = Bits32(opcode, 3, 0);
7879 setflags = BitIsSet(opcode, 20);
7880 shift_n = DecodeImmShiftARM(opcode, shift_t);
7881 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7882 // TODO: Emulate SUBS PC, LR and related instructions.
7883 if (Rd == 15 && setflags)
7884 return false;
7885 break;
7886 default:
7887 return false;
7888 }
7889 // Read the register value from register Rn.
7890 uint32_t val1 = ReadCoreReg(Rn, &success);
7891 if (!success)
7892 return false;
7893
7894 // Read the register value from register Rm.
7895 uint32_t val2 = ReadCoreReg(Rm, &success);
7896 if (!success)
7897 return false;
7898
7899 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7900 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
7901
7902 EmulateInstruction::Context context;
7903 context.type = EmulateInstruction::eContextImmediate;
7904 context.SetNoArgs();
7905 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7906 return false;
7907
7908 return true;
7909}
7910
Johnny Chen90e607b2011-02-23 00:07:09 +00007911// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
7912// an immediate value, and writes the result to the destination register. It can optionally update the condition
7913// flags based on the result.
7914bool
7915EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
7916{
7917#if 0
7918 // ARM pseudo code...
7919 if ConditionPassed() then
7920 EncodingSpecificOperations();
7921 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
7922 if d == 15 then
7923 ALUWritePC(result); // setflags is always FALSE here
7924 else
7925 R[d] = result;
7926 if setflags then
7927 APSR.N = result<31>;
7928 APSR.Z = IsZeroBit(result);
7929 APSR.C = carry;
7930 APSR.V = overflow;
7931#endif
7932
7933 bool success = false;
7934 const uint32_t opcode = OpcodeAsUnsigned (&success);
7935 if (!success)
7936 return false;
7937
7938 uint32_t Rd; // the destination register
7939 uint32_t Rn; // the first operand
7940 bool setflags;
7941 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7942 switch (encoding) {
7943 case eEncodingA1:
7944 Rd = Bits32(opcode, 15, 12);
7945 Rn = Bits32(opcode, 19, 16);
7946 setflags = BitIsSet(opcode, 20);
7947 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7948 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7949 // TODO: Emulate SUBS PC, LR and related instructions.
7950 if (Rd == 15 && setflags)
7951 return false;
7952 break;
7953 default:
7954 return false;
7955 }
7956 // Read the register value from the operand register Rn.
7957 uint32_t reg_val = ReadCoreReg(Rn, &success);
7958 if (!success)
7959 return false;
7960
7961 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
7962
7963 EmulateInstruction::Context context;
7964 context.type = EmulateInstruction::eContextImmediate;
7965 context.SetNoArgs ();
7966
7967 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7968 return false;
7969
7970 return true;
7971}
7972
7973// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
7974// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
7975// condition flags based on the result.
7976bool
7977EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
7978{
7979#if 0
7980 // ARM pseudo code...
7981 if ConditionPassed() then
7982 EncodingSpecificOperations();
7983 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7984 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
7985 if d == 15 then
7986 ALUWritePC(result); // setflags is always FALSE here
7987 else
7988 R[d] = result;
7989 if setflags then
7990 APSR.N = result<31>;
7991 APSR.Z = IsZeroBit(result);
7992 APSR.C = carry;
7993 APSR.V = overflow;
7994#endif
7995
7996 bool success = false;
7997 const uint32_t opcode = OpcodeAsUnsigned (&success);
7998 if (!success)
7999 return false;
8000
8001 uint32_t Rd; // the destination register
8002 uint32_t Rn; // the first operand
8003 uint32_t Rm; // the second operand
8004 bool setflags;
8005 ARM_ShifterType shift_t;
8006 uint32_t shift_n; // the shift applied to the value read from Rm
8007 switch (encoding) {
8008 case eEncodingA1:
8009 Rd = Bits32(opcode, 15, 12);
8010 Rn = Bits32(opcode, 19, 16);
8011 Rm = Bits32(opcode, 3, 0);
8012 setflags = BitIsSet(opcode, 20);
8013 shift_n = DecodeImmShiftARM(opcode, shift_t);
8014 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8015 // TODO: Emulate SUBS PC, LR and related instructions.
8016 if (Rd == 15 && setflags)
8017 return false;
8018 break;
8019 default:
8020 return false;
8021 }
8022 // Read the register value from register Rn.
8023 uint32_t val1 = ReadCoreReg(Rn, &success);
8024 if (!success)
8025 return false;
8026
8027 // Read the register value from register Rm.
8028 uint32_t val2 = ReadCoreReg(Rm, &success);
8029 if (!success)
8030 return false;
8031
8032 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8033 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8034
8035 EmulateInstruction::Context context;
8036 context.type = EmulateInstruction::eContextImmediate;
8037 context.SetNoArgs();
8038 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8039 return false;
8040
8041 return true;
8042}
8043
Johnny Chen9b381772011-02-23 01:01:21 +00008044// Subtract with Carry (immediate) subtracts an immediate value and the value of
8045// NOT (Carry flag) from a register value, and writes the result to the destination register.
8046// It can optionally update the condition flags based on the result.
8047bool
8048EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8049{
8050#if 0
8051 // ARM pseudo code...
8052 if ConditionPassed() then
8053 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008054 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008055 if d == 15 then // Can only occur for ARM encoding
8056 ALUWritePC(result); // setflags is always FALSE here
8057 else
8058 R[d] = result;
8059 if setflags then
8060 APSR.N = result<31>;
8061 APSR.Z = IsZeroBit(result);
8062 APSR.C = carry;
8063 APSR.V = overflow;
8064#endif
8065
8066 bool success = false;
8067 const uint32_t opcode = OpcodeAsUnsigned (&success);
8068 if (!success)
8069 return false;
8070
8071 uint32_t Rd; // the destination register
8072 uint32_t Rn; // the first operand
8073 bool setflags;
8074 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8075 switch (encoding) {
8076 case eEncodingT1:
8077 Rd = Bits32(opcode, 11, 8);
8078 Rn = Bits32(opcode, 19, 16);
8079 setflags = BitIsSet(opcode, 20);
8080 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8081 if (BadReg(Rd) || BadReg(Rn))
8082 return false;
8083 break;
8084 case eEncodingA1:
8085 Rd = Bits32(opcode, 15, 12);
8086 Rn = Bits32(opcode, 19, 16);
8087 setflags = BitIsSet(opcode, 20);
8088 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8089 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8090 // TODO: Emulate SUBS PC, LR and related instructions.
8091 if (Rd == 15 && setflags)
8092 return false;
8093 break;
8094 default:
8095 return false;
8096 }
8097 // Read the register value from the operand register Rn.
8098 uint32_t reg_val = ReadCoreReg(Rn, &success);
8099 if (!success)
8100 return false;
8101
8102 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8103
8104 EmulateInstruction::Context context;
8105 context.type = EmulateInstruction::eContextImmediate;
8106 context.SetNoArgs ();
8107
8108 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8109 return false;
8110
8111 return true;
8112}
8113
8114// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8115// NOT (Carry flag) from a register value, and writes the result to the destination register.
8116// It can optionally update the condition flags based on the result.
8117bool
8118EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8119{
8120#if 0
8121 // ARM pseudo code...
8122 if ConditionPassed() then
8123 EncodingSpecificOperations();
8124 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8125 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8126 if d == 15 then // Can only occur for ARM encoding
8127 ALUWritePC(result); // setflags is always FALSE here
8128 else
8129 R[d] = result;
8130 if setflags then
8131 APSR.N = result<31>;
8132 APSR.Z = IsZeroBit(result);
8133 APSR.C = carry;
8134 APSR.V = overflow;
8135#endif
8136
8137 bool success = false;
8138 const uint32_t opcode = OpcodeAsUnsigned (&success);
8139 if (!success)
8140 return false;
8141
8142 uint32_t Rd; // the destination register
8143 uint32_t Rn; // the first operand
8144 uint32_t Rm; // the second operand
8145 bool setflags;
8146 ARM_ShifterType shift_t;
8147 uint32_t shift_n; // the shift applied to the value read from Rm
8148 switch (encoding) {
8149 case eEncodingT1:
8150 Rd = Rn = Bits32(opcode, 2, 0);
8151 Rm = Bits32(opcode, 5, 3);
8152 setflags = !InITBlock();
8153 shift_t = SRType_LSL;
8154 shift_n = 0;
8155 break;
8156 case eEncodingT2:
8157 Rd = Bits32(opcode, 11, 8);
8158 Rn = Bits32(opcode, 19, 16);
8159 Rm = Bits32(opcode, 3, 0);
8160 setflags = BitIsSet(opcode, 20);
8161 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8162 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8163 return false;
8164 break;
8165 case eEncodingA1:
8166 Rd = Bits32(opcode, 15, 12);
8167 Rn = Bits32(opcode, 19, 16);
8168 Rm = Bits32(opcode, 3, 0);
8169 setflags = BitIsSet(opcode, 20);
8170 shift_n = DecodeImmShiftARM(opcode, shift_t);
8171 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8172 // TODO: Emulate SUBS PC, LR and related instructions.
8173 if (Rd == 15 && setflags)
8174 return false;
8175 break;
8176 default:
8177 return false;
8178 }
8179 // Read the register value from register Rn.
8180 uint32_t val1 = ReadCoreReg(Rn, &success);
8181 if (!success)
8182 return false;
8183
8184 // Read the register value from register Rm.
8185 uint32_t val2 = ReadCoreReg(Rm, &success);
8186 if (!success)
8187 return false;
8188
8189 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8190 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8191
8192 EmulateInstruction::Context context;
8193 context.type = EmulateInstruction::eContextImmediate;
8194 context.SetNoArgs();
8195 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8196 return false;
8197
8198 return true;
8199}
8200
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008201// This instruction subtracts an immediate value from a register value, and writes the result
8202// to the destination register. It can optionally update the condition flags based on the result.
8203bool
8204EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8205{
8206#if 0
8207 // ARM pseudo code...
8208 if ConditionPassed() then
8209 EncodingSpecificOperations();
8210 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8211 R[d] = result;
8212 if setflags then
8213 APSR.N = result<31>;
8214 APSR.Z = IsZeroBit(result);
8215 APSR.C = carry;
8216 APSR.V = overflow;
8217#endif
8218
8219 bool success = false;
8220 const uint32_t opcode = OpcodeAsUnsigned (&success);
8221 if (!success)
8222 return false;
8223
8224 uint32_t Rd; // the destination register
8225 uint32_t Rn; // the first operand
8226 bool setflags;
8227 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8228 switch (encoding) {
8229 case eEncodingT1:
8230 Rd = Bits32(opcode, 2, 0);
8231 Rn = Bits32(opcode, 5, 3);
8232 setflags = !InITBlock();
8233 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8234 break;
8235 case eEncodingT2:
8236 Rd = Rn = Bits32(opcode, 10, 8);
8237 setflags = !InITBlock();
8238 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8239 break;
8240 case eEncodingT3:
8241 Rd = Bits32(opcode, 11, 8);
8242 Rn = Bits32(opcode, 19, 16);
8243 setflags = BitIsSet(opcode, 20);
8244 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8245
8246 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8247 if (Rd == 15 && setflags)
8248 return EmulateCMPImm(eEncodingT2);
8249
8250 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8251 if (Rn == 13)
8252 return EmulateSUBSPImm(eEncodingT2);
8253
8254 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8255 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8256 return false;
8257 break;
8258 case eEncodingT4:
8259 Rd = Bits32(opcode, 11, 8);
8260 Rn = Bits32(opcode, 19, 16);
8261 setflags = BitIsSet(opcode, 20);
8262 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8263
8264 // if Rn == '1111' then SEE ADR;
8265 if (Rn == 15)
8266 return EmulateADR(eEncodingT2);
8267
8268 // if Rn == '1101' then SEE SUB (SP minus immediate);
8269 if (Rn == 13)
8270 return EmulateSUBSPImm(eEncodingT3);
8271
8272 if (BadReg(Rd))
8273 return false;
8274 break;
8275 default:
8276 return false;
8277 }
8278 // Read the register value from the operand register Rn.
8279 uint32_t reg_val = ReadCoreReg(Rn, &success);
8280 if (!success)
8281 return false;
8282
8283 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8284
8285 EmulateInstruction::Context context;
8286 context.type = EmulateInstruction::eContextImmediate;
8287 context.SetNoArgs ();
8288
8289 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8290 return false;
8291
8292 return true;
8293}
8294
8295// This instruction subtracts an immediate value from a register value, and writes the result
8296// to the destination register. It can optionally update the condition flags based on the result.
8297bool
8298EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8299{
8300#if 0
8301 // ARM pseudo code...
8302 if ConditionPassed() then
8303 EncodingSpecificOperations();
8304 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8305 if d == 15 then
8306 ALUWritePC(result); // setflags is always FALSE here
8307 else
8308 R[d] = result;
8309 if setflags then
8310 APSR.N = result<31>;
8311 APSR.Z = IsZeroBit(result);
8312 APSR.C = carry;
8313 APSR.V = overflow;
8314#endif
8315
8316 bool success = false;
8317 const uint32_t opcode = OpcodeAsUnsigned (&success);
8318 if (!success)
8319 return false;
8320
8321 uint32_t Rd; // the destination register
8322 uint32_t Rn; // the first operand
8323 bool setflags;
8324 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8325 switch (encoding) {
8326 case eEncodingA1:
8327 Rd = Bits32(opcode, 15, 12);
8328 Rn = Bits32(opcode, 19, 16);
8329 setflags = BitIsSet(opcode, 20);
8330 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8331
8332 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8333 if (Rn == 15 && !setflags)
8334 return EmulateADR(eEncodingA2);
8335
8336 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8337 if (Rn == 13)
8338 return EmulateSUBSPImm(eEncodingA1);
8339
8340 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8341 // TODO: Emulate SUBS PC, LR and related instructions.
8342 if (Rd == 15 && setflags)
8343 return false;
8344 break;
8345 default:
8346 return false;
8347 }
8348 // Read the register value from the operand register Rn.
8349 uint32_t reg_val = ReadCoreReg(Rn, &success);
8350 if (!success)
8351 return false;
8352
8353 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8354
8355 EmulateInstruction::Context context;
8356 context.type = EmulateInstruction::eContextImmediate;
8357 context.SetNoArgs ();
8358
8359 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8360 return false;
8361
8362 return true;
8363}
8364
Johnny Chen2115b412011-02-21 23:42:44 +00008365// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8366// immediate value. It updates the condition flags based on the result, and discards the result.
8367bool
8368EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
8369{
8370#if 0
8371 // ARM pseudo code...
8372 if ConditionPassed() then
8373 EncodingSpecificOperations();
8374 result = R[n] EOR imm32;
8375 APSR.N = result<31>;
8376 APSR.Z = IsZeroBit(result);
8377 APSR.C = carry;
8378 // APSR.V unchanged
8379#endif
8380
8381 bool success = false;
8382 const uint32_t opcode = OpcodeAsUnsigned (&success);
8383 if (!success)
8384 return false;
8385
8386 if (ConditionPassed())
8387 {
8388 uint32_t Rn;
8389 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8390 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8391 switch (encoding)
8392 {
8393 case eEncodingT1:
8394 Rn = Bits32(opcode, 19, 16);
8395 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8396 if (BadReg(Rn))
8397 return false;
8398 break;
8399 case eEncodingA1:
8400 Rn = Bits32(opcode, 19, 16);
8401 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8402 break;
8403 default:
8404 return false;
8405 }
8406
8407 // Read the first operand.
8408 uint32_t val1 = ReadCoreReg(Rn, &success);
8409 if (!success)
8410 return false;
8411
8412 uint32_t result = val1 ^ imm32;
8413
8414 EmulateInstruction::Context context;
8415 context.type = EmulateInstruction::eContextImmediate;
8416 context.SetNoArgs ();
8417
8418 if (!WriteFlags(context, result, carry))
8419 return false;
8420 }
8421 return true;
8422}
8423
8424// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8425// optionally-shifted register value. It updates the condition flags based on the result, and discards
8426// the result.
8427bool
8428EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
8429{
8430#if 0
8431 // ARM pseudo code...
8432 if ConditionPassed() then
8433 EncodingSpecificOperations();
8434 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8435 result = R[n] EOR shifted;
8436 APSR.N = result<31>;
8437 APSR.Z = IsZeroBit(result);
8438 APSR.C = carry;
8439 // APSR.V unchanged
8440#endif
8441
8442 bool success = false;
8443 const uint32_t opcode = OpcodeAsUnsigned (&success);
8444 if (!success)
8445 return false;
8446
8447 if (ConditionPassed())
8448 {
8449 uint32_t Rn, Rm;
8450 ARM_ShifterType shift_t;
8451 uint32_t shift_n; // the shift applied to the value read from Rm
8452 uint32_t carry;
8453 switch (encoding)
8454 {
8455 case eEncodingT1:
8456 Rn = Bits32(opcode, 19, 16);
8457 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008458 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008459 if (BadReg(Rn) || BadReg(Rm))
8460 return false;
8461 break;
8462 case eEncodingA1:
8463 Rn = Bits32(opcode, 19, 16);
8464 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008465 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008466 break;
8467 default:
8468 return false;
8469 }
8470
8471 // Read the first operand.
8472 uint32_t val1 = ReadCoreReg(Rn, &success);
8473 if (!success)
8474 return false;
8475
8476 // Read the second operand.
8477 uint32_t val2 = ReadCoreReg(Rm, &success);
8478 if (!success)
8479 return false;
8480
8481 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8482 uint32_t result = val1 ^ shifted;
8483
8484 EmulateInstruction::Context context;
8485 context.type = EmulateInstruction::eContextImmediate;
8486 context.SetNoArgs ();
8487
8488 if (!WriteFlags(context, result, carry))
8489 return false;
8490 }
8491 return true;
8492}
8493
Johnny Chende3cce32011-02-21 21:24:49 +00008494// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8495// It updates the condition flags based on the result, and discards the result.
8496bool
8497EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8498{
8499#if 0
8500 // ARM pseudo code...
8501 if ConditionPassed() then
8502 EncodingSpecificOperations();
8503 result = R[n] AND imm32;
8504 APSR.N = result<31>;
8505 APSR.Z = IsZeroBit(result);
8506 APSR.C = carry;
8507 // APSR.V unchanged
8508#endif
8509
8510 bool success = false;
8511 const uint32_t opcode = OpcodeAsUnsigned (&success);
8512 if (!success)
8513 return false;
8514
8515 if (ConditionPassed())
8516 {
8517 uint32_t Rn;
8518 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8519 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8520 switch (encoding)
8521 {
8522 case eEncodingT1:
8523 Rn = Bits32(opcode, 19, 16);
8524 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8525 if (BadReg(Rn))
8526 return false;
8527 break;
8528 case eEncodingA1:
8529 Rn = Bits32(opcode, 19, 16);
8530 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8531 break;
8532 default:
8533 return false;
8534 }
8535
8536 // Read the first operand.
8537 uint32_t val1 = ReadCoreReg(Rn, &success);
8538 if (!success)
8539 return false;
8540
8541 uint32_t result = val1 & imm32;
8542
8543 EmulateInstruction::Context context;
8544 context.type = EmulateInstruction::eContextImmediate;
8545 context.SetNoArgs ();
8546
8547 if (!WriteFlags(context, result, carry))
8548 return false;
8549 }
8550 return true;
8551}
8552
8553// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
8554// It updates the condition flags based on the result, and discards the result.
8555bool
8556EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
8557{
8558#if 0
8559 // ARM pseudo code...
8560 if ConditionPassed() then
8561 EncodingSpecificOperations();
8562 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8563 result = R[n] AND shifted;
8564 APSR.N = result<31>;
8565 APSR.Z = IsZeroBit(result);
8566 APSR.C = carry;
8567 // APSR.V unchanged
8568#endif
8569
8570 bool success = false;
8571 const uint32_t opcode = OpcodeAsUnsigned (&success);
8572 if (!success)
8573 return false;
8574
8575 if (ConditionPassed())
8576 {
8577 uint32_t Rn, Rm;
8578 ARM_ShifterType shift_t;
8579 uint32_t shift_n; // the shift applied to the value read from Rm
8580 uint32_t carry;
8581 switch (encoding)
8582 {
8583 case eEncodingT1:
8584 Rn = Bits32(opcode, 2, 0);
8585 Rm = Bits32(opcode, 5, 3);
8586 shift_t = SRType_LSL;
8587 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008588 break;
Johnny Chende3cce32011-02-21 21:24:49 +00008589 case eEncodingT2:
8590 Rn = Bits32(opcode, 19, 16);
8591 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008592 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008593 if (BadReg(Rn) || BadReg(Rm))
8594 return false;
8595 break;
8596 case eEncodingA1:
8597 Rn = Bits32(opcode, 19, 16);
8598 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008599 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008600 break;
8601 default:
8602 return false;
8603 }
8604
8605 // Read the first operand.
8606 uint32_t val1 = ReadCoreReg(Rn, &success);
8607 if (!success)
8608 return false;
8609
8610 // Read the second operand.
8611 uint32_t val2 = ReadCoreReg(Rm, &success);
8612 if (!success)
8613 return false;
8614
8615 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8616 uint32_t result = val1 & shifted;
8617
8618 EmulateInstruction::Context context;
8619 context.type = EmulateInstruction::eContextImmediate;
8620 context.SetNoArgs ();
8621
8622 if (!WriteFlags(context, result, carry))
8623 return false;
8624 }
8625 return true;
8626}
8627
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008628EmulateInstructionARM::ARMOpcode*
8629EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00008630{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008631 static ARMOpcode
8632 g_arm_opcodes[] =
8633 {
8634 //----------------------------------------------------------------------
8635 // Prologue instructions
8636 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00008637
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008638 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008639 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8640 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00008641
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008642 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008643 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008644 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00008645 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00008646 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
8647 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008648 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00008649
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008650 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008651 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00008652
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008653 // push one register
8654 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00008655 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00008656
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008657 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00008658 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8659 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00008660
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008661 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00008662 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008663 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00008664
Johnny Chen9f687722011-02-18 00:02:28 +00008665 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8666 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00008667 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008668 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
8669
8670 //----------------------------------------------------------------------
8671 // Supervisor Call (previously Software Interrupt)
8672 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008673 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
8674
8675 //----------------------------------------------------------------------
8676 // Branch instructions
8677 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00008678 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00008679 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
8680 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8681 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8682 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008683 // for example, "bx lr"
8684 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008685 // bxj
8686 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008687
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008688 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00008689 // Data-processing instructions
8690 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008691 // adc (immediate)
8692 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
8693 // adc (register)
8694 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008695 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008696 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008697 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008698 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00008699 // adr
8700 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8701 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008702 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008703 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008704 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008705 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008706 // bic (immediate)
8707 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
8708 // bic (register)
8709 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008710 // eor (immediate)
8711 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
8712 // eor (register)
8713 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008714 // orr (immediate)
8715 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
8716 // orr (register)
8717 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008718 // rsb (immediate)
8719 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
8720 // rsb (register)
8721 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00008722 // rsc (immediate)
8723 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
8724 // rsc (register)
8725 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008726 // sbc (immediate)
8727 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8728 // sbc (register)
8729 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008730 // sub (immediate, ARM)
8731 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008732 // sub (sp minus immediate)
8733 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00008734 // teq (immediate)
8735 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
8736 // teq (register)
8737 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008738 // tst (immediate)
8739 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
8740 // tst (register)
8741 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
8742
8743
Johnny Chen01d61572011-02-25 00:23:25 +00008744 // mov (register)
8745 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008746 // mvn (immediate)
8747 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
8748 // mvn (register)
8749 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00008750 // cmn (immediate)
8751 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
8752 // cmn (register)
8753 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008754 // cmp (immediate)
8755 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
8756 // cmp (register)
8757 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008758 // asr (immediate)
8759 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008760 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00008761 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008762 // lsl (immediate)
8763 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
8764 // lsl (register)
8765 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
8766 // lsr (immediate)
8767 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
8768 // lsr (register)
8769 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008770 // rrx is a special case encoding of ror (immediate)
8771 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
8772 // ror (immediate)
8773 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
8774 // ror (register)
8775 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00008776 // mul
8777 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00008778
8779 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008780 // Load instructions
8781 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00008782 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00008783 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00008784 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008785 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00008786 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00008787 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00008788 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00008789 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008790 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008791 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008792 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008793 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008794 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008795 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00008796 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
8797 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00008798
8799 //----------------------------------------------------------------------
8800 // Store instructions
8801 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00008802 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008803 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00008804 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00008805 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
8806 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00008807
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008808
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008809 };
8810 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
8811
8812 for (size_t i=0; i<k_num_arm_opcodes; ++i)
8813 {
8814 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
8815 return &g_arm_opcodes[i];
8816 }
8817 return NULL;
8818}
Greg Clayton64c84432011-01-21 22:02:52 +00008819
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008820
8821EmulateInstructionARM::ARMOpcode*
8822EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00008823{
Johnny Chenfdd179e2011-01-31 20:09:28 +00008824
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008825 static ARMOpcode
8826 g_thumb_opcodes[] =
8827 {
8828 //----------------------------------------------------------------------
8829 // Prologue instructions
8830 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00008831
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008832 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008833 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8834 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
8835 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00008836
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008837 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008838 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008839 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00008840 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008841 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00008842 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00008843
Johnny Chen864a8e82011-02-18 00:07:39 +00008844 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00008845 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00008846
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008847 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008848 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008849 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00008850 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
8851 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008852
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008853 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00008854 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8855 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008856
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008857 //----------------------------------------------------------------------
8858 // Epilogue instructions
8859 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00008860
Johnny Chen864a8e82011-02-18 00:07:39 +00008861 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00008862 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8863 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
8864 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00008865 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
8866 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008867
8868 //----------------------------------------------------------------------
8869 // Supervisor Call (previously Software Interrupt)
8870 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00008871 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
8872
8873 //----------------------------------------------------------------------
8874 // If Then makes up to four following instructions conditional.
8875 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008876 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
8877
8878 //----------------------------------------------------------------------
8879 // Branch instructions
8880 //----------------------------------------------------------------------
8881 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
8882 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008883 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00008884 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008885 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00008886 // J1 == J2 == 1
8887 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8888 // J1 == J2 == 1
8889 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8890 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008891 // for example, "bx lr"
8892 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008893 // bxj
8894 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00008895 // compare and branch
8896 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00008897 // table branch byte
8898 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
8899 // table branch halfword
8900 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008901
8902 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00008903 // Data-processing instructions
8904 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008905 // adc (immediate)
8906 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
8907 // adc (register)
8908 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
8909 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
8910 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00008911 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00008912 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00008913 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00008914 // adr
8915 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8916 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
8917 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008918 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008919 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008920 // and (register)
8921 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
8922 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008923 // bic (immediate)
8924 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
8925 // bic (register)
8926 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
8927 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008928 // eor (immediate)
8929 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
8930 // eor (register)
8931 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
8932 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008933 // orr (immediate)
8934 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
8935 // orr (register)
8936 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
8937 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008938 // rsb (immediate)
8939 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
8940 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
8941 // rsb (register)
8942 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008943 // sbc (immediate)
8944 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8945 // sbc (register)
8946 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
8947 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00008948 // add (immediate, Thumb)
8949 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
8950 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
8951 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
8952 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008953 // sub (immediate, Thumb)
8954 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
8955 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
8956 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
8957 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008958 // sub (sp minus immediate)
8959 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
8960 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00008961 // teq (immediate)
8962 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
8963 // teq (register)
8964 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008965 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00008966 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00008967 // tst (register)
8968 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
8969 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
8970
Johnny Chen7c5234d2011-02-18 23:41:11 +00008971
Johnny Chen338bf542011-02-10 19:29:03 +00008972 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00008973 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00008974 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00008975 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008976 // mov{s}<c>.w <Rd>, <Rm>
8977 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00008978 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00008979 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
8980 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008981 // mvn (immediate)
8982 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
8983 // mvn (register)
8984 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
8985 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008986 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00008987 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008988 // cmn (register)
8989 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008990 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008991 // cmp (immediate)
8992 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008993 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008994 // cmp (register) (Rn and Rm both from r0-r7)
8995 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
8996 // cmp (register) (Rn and Rm not both from r0-r7)
8997 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008998 // asr (immediate)
8999 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009000 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009001 // asr (register)
9002 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9003 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009004 // lsl (immediate)
9005 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9006 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9007 // lsl (register)
9008 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9009 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9010 // lsr (immediate)
9011 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9012 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9013 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009014 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009015 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009016 // rrx is a special case encoding of ror (immediate)
9017 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9018 // ror (immediate)
9019 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9020 // ror (register)
9021 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9022 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009023 // mul
9024 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9025 // mul
9026 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Johnny Chen26863dc2011-02-09 23:43:29 +00009027
9028 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009029 // Load instructions
9030 //----------------------------------------------------------------------
9031 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009032 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009033 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009034 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9035 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009036 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009037 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9038 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009039 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9040 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9041 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009042 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009043 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9044 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009045 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9046 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9047 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009048 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009049 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9050 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009051 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9052 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009053 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009054 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9055 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009056 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9057 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009058 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009059 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9060 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009061
9062 //----------------------------------------------------------------------
9063 // Store instructions
9064 //----------------------------------------------------------------------
9065 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009066 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009067 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009068 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9069 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9070 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9071 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9072 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9073 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9074 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9075 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
9076 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009077 };
9078
9079 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9080 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9081 {
9082 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9083 return &g_thumb_opcodes[i];
9084 }
9085 return NULL;
9086}
Greg Clayton64c84432011-01-21 22:02:52 +00009087
Greg Clayton31e2a382011-01-30 20:03:56 +00009088bool
Greg Clayton395fc332011-02-15 21:59:32 +00009089EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009090{
9091 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009092 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009093 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009094 {
Greg Clayton395fc332011-02-15 21:59:32 +00009095 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9096 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9097 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9098 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9099 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9100 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9101 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9102 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9103 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9104 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009105 }
9106 return m_arm_isa != 0;
9107}
9108
9109
Greg Clayton64c84432011-01-21 22:02:52 +00009110bool
9111EmulateInstructionARM::ReadInstruction ()
9112{
9113 bool success = false;
9114 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9115 if (success)
9116 {
9117 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9118 if (success)
9119 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009120 Context read_inst_context;
9121 read_inst_context.type = eContextReadOpcode;
9122 read_inst_context.SetNoArgs ();
9123
Greg Clayton64c84432011-01-21 22:02:52 +00009124 if (m_inst_cpsr & MASK_CPSR_T)
9125 {
9126 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009127 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009128
9129 if (success)
9130 {
9131 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9132 {
9133 m_inst.opcode_type = eOpcode16;
9134 m_inst.opcode.inst16 = thumb_opcode;
9135 }
9136 else
9137 {
9138 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009139 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009140 }
9141 }
9142 }
9143 else
9144 {
9145 m_inst_mode = eModeARM;
9146 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009147 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009148 }
9149 }
9150 }
9151 if (!success)
9152 {
9153 m_inst_mode = eModeInvalid;
9154 m_inst_pc = LLDB_INVALID_ADDRESS;
9155 }
9156 return success;
9157}
9158
Johnny Chenee9b1f72011-02-09 01:00:31 +00009159uint32_t
9160EmulateInstructionARM::ArchVersion ()
9161{
9162 return m_arm_isa;
9163}
9164
Greg Clayton64c84432011-01-21 22:02:52 +00009165bool
9166EmulateInstructionARM::ConditionPassed ()
9167{
9168 if (m_inst_cpsr == 0)
9169 return false;
9170
9171 const uint32_t cond = CurrentCond ();
9172
9173 if (cond == UINT32_MAX)
9174 return false;
9175
9176 bool result = false;
9177 switch (UnsignedBits(cond, 3, 1))
9178 {
9179 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9180 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9181 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9182 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9183 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9184 case 5:
9185 {
9186 bool n = (m_inst_cpsr & MASK_CPSR_N);
9187 bool v = (m_inst_cpsr & MASK_CPSR_V);
9188 result = n == v;
9189 }
9190 break;
9191 case 6:
9192 {
9193 bool n = (m_inst_cpsr & MASK_CPSR_N);
9194 bool v = (m_inst_cpsr & MASK_CPSR_V);
9195 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9196 }
9197 break;
9198 case 7:
9199 result = true;
9200 break;
9201 }
9202
9203 if (cond & 1)
9204 result = !result;
9205 return result;
9206}
9207
Johnny Chen9ee056b2011-02-08 00:06:35 +00009208uint32_t
9209EmulateInstructionARM::CurrentCond ()
9210{
9211 switch (m_inst_mode)
9212 {
9213 default:
9214 case eModeInvalid:
9215 break;
9216
9217 case eModeARM:
9218 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9219
9220 case eModeThumb:
9221 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9222 // 'cond' field of the encoding.
9223 if (m_inst.opcode_type == eOpcode16 &&
9224 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9225 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9226 {
9227 return Bits32(m_inst.opcode.inst16, 11, 7);
9228 }
9229 else if (m_inst.opcode_type == eOpcode32 &&
9230 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9231 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9232 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9233 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9234 {
9235 return Bits32(m_inst.opcode.inst32, 25, 22);
9236 }
9237
9238 return m_it_session.GetCond();
9239 }
9240 return UINT32_MAX; // Return invalid value
9241}
9242
Johnny Chen9ee056b2011-02-08 00:06:35 +00009243bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009244EmulateInstructionARM::InITBlock()
9245{
9246 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9247}
9248
9249bool
9250EmulateInstructionARM::LastInITBlock()
9251{
9252 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9253}
9254
9255bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009256EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9257{
9258 addr_t target;
9259
Johnny Chenee9b1f72011-02-09 01:00:31 +00009260 // Check the current instruction set.
9261 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009262 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009263 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009264 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009265
Johnny Chen9ee056b2011-02-08 00:06:35 +00009266 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009267 return false;
9268
9269 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009270}
9271
9272// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9273bool
Johnny Chen668b4512011-02-15 21:08:58 +00009274EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009275{
9276 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009277 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9278 // we want to record it and issue a WriteRegister callback so the clients
9279 // can track the mode changes accordingly.
9280 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009281
9282 if (BitIsSet(addr, 0))
9283 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009284 if (CurrentInstrSet() != eModeThumb)
9285 {
9286 SelectInstrSet(eModeThumb);
9287 cpsr_changed = true;
9288 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009289 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009290 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009291 }
9292 else if (BitIsClear(addr, 1))
9293 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009294 if (CurrentInstrSet() != eModeARM)
9295 {
9296 SelectInstrSet(eModeARM);
9297 cpsr_changed = true;
9298 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009299 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009300 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009301 }
9302 else
9303 return false; // address<1:0> == '10' => UNPREDICTABLE
9304
Johnny Chen0f309db2011-02-09 19:11:32 +00009305 if (cpsr_changed)
9306 {
Johnny Chen558133b2011-02-09 23:59:17 +00009307 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009308 return false;
9309 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009311 return false;
9312
9313 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009314}
Greg Clayton64c84432011-01-21 22:02:52 +00009315
Johnny Chenee9b1f72011-02-09 01:00:31 +00009316// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9317bool
Johnny Chen668b4512011-02-15 21:08:58 +00009318EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009319{
9320 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009321 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009322 else
9323 return BranchWritePC((const Context)context, addr);
9324}
9325
Johnny Chen26863dc2011-02-09 23:43:29 +00009326// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9327bool
Johnny Chen668b4512011-02-15 21:08:58 +00009328EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009329{
9330 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009331 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009332 else
9333 return BranchWritePC((const Context)context, addr);
9334}
9335
Johnny Chenee9b1f72011-02-09 01:00:31 +00009336EmulateInstructionARM::Mode
9337EmulateInstructionARM::CurrentInstrSet ()
9338{
9339 return m_inst_mode;
9340}
9341
9342// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009343// ReadInstruction() is performed. This function has a side effect of updating
9344// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009345bool
9346EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9347{
Johnny Chen558133b2011-02-09 23:59:17 +00009348 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009349 switch (arm_or_thumb)
9350 {
9351 default:
9352 return false;
9353 eModeARM:
9354 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009355 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009356 break;
9357 eModeThumb:
9358 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009359 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009360 break;
9361 }
9362 return true;
9363}
9364
Johnny Chenef21b592011-02-10 01:52:38 +00009365// This function returns TRUE if the processor currently provides support for
9366// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9367// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9368bool
9369EmulateInstructionARM::UnalignedSupport()
9370{
9371 return (ArchVersion() >= ARMv7);
9372}
9373
Johnny Chenbf6ad172011-02-11 01:29:53 +00009374// The main addition and subtraction instructions can produce status information
9375// about both unsigned carry and signed overflow conditions. This status
9376// information can be used to synthesize multi-word additions and subtractions.
9377EmulateInstructionARM::AddWithCarryResult
9378EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9379{
9380 uint32_t result;
9381 uint8_t carry_out;
9382 uint8_t overflow;
9383
9384 uint64_t unsigned_sum = x + y + carry_in;
9385 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9386
9387 result = UnsignedBits(unsigned_sum, 31, 0);
9388 carry_out = (result == unsigned_sum ? 0 : 1);
9389 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9390
9391 AddWithCarryResult res = { result, carry_out, overflow };
9392 return res;
9393}
9394
Johnny Chen157b9592011-02-18 21:13:05 +00009395uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00009396EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00009397{
Johnny Chene39f22d2011-02-19 01:36:13 +00009398 uint32_t reg_kind, reg_num;
9399 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00009400 {
Johnny Chene39f22d2011-02-19 01:36:13 +00009401 case SP_REG:
9402 reg_kind = eRegisterKindGeneric;
9403 reg_num = LLDB_REGNUM_GENERIC_SP;
9404 break;
9405 case LR_REG:
9406 reg_kind = eRegisterKindGeneric;
9407 reg_num = LLDB_REGNUM_GENERIC_RA;
9408 break;
9409 case PC_REG:
9410 reg_kind = eRegisterKindGeneric;
9411 reg_num = LLDB_REGNUM_GENERIC_PC;
9412 break;
9413 default:
9414 if (0 <= num && num < SP_REG)
9415 {
9416 reg_kind = eRegisterKindDWARF;
9417 reg_num = dwarf_r0 + num;
9418 }
Johnny Chen157b9592011-02-18 21:13:05 +00009419 else
Johnny Chene39f22d2011-02-19 01:36:13 +00009420 {
9421 assert(0 && "Invalid register number");
9422 *success = false;
9423 return ~0u;
9424 }
9425 break;
Johnny Chen157b9592011-02-18 21:13:05 +00009426 }
Johnny Chene39f22d2011-02-19 01:36:13 +00009427
9428 // Read our register.
9429 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
9430
9431 // When executing an ARM instruction , PC reads as the address of the current
9432 // instruction plus 8.
9433 // When executing a Thumb instruction , PC reads as the address of the current
9434 // instruction plus 4.
9435 if (num == 15)
9436 {
9437 if (CurrentInstrSet() == eModeARM)
9438 val += 8;
9439 else
9440 val += 4;
9441 }
Johnny Chen157b9592011-02-18 21:13:05 +00009442
9443 return val;
9444}
9445
Johnny Chenca67d1c2011-02-17 01:35:27 +00009446// Write the result to the ARM core register Rd, and optionally update the
9447// condition flags based on the result.
9448//
9449// This helper method tries to encapsulate the following pseudocode from the
9450// ARM Architecture Reference Manual:
9451//
9452// if d == 15 then // Can only occur for encoding A1
9453// ALUWritePC(result); // setflags is always FALSE here
9454// else
9455// R[d] = result;
9456// if setflags then
9457// APSR.N = result<31>;
9458// APSR.Z = IsZeroBit(result);
9459// APSR.C = carry;
9460// // APSR.V unchanged
9461//
9462// In the above case, the API client does not pass in the overflow arg, which
9463// defaults to ~0u.
9464bool
Johnny Chen10530c22011-02-17 22:37:12 +00009465EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
9466 const uint32_t result,
9467 const uint32_t Rd,
9468 bool setflags,
9469 const uint32_t carry,
9470 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00009471{
9472 if (Rd == 15)
9473 {
9474 if (!ALUWritePC (context, result))
9475 return false;
9476 }
9477 else
9478 {
Johnny Chena695f952011-02-23 21:24:25 +00009479 uint32_t reg_kind, reg_num;
9480 switch (Rd)
9481 {
9482 case SP_REG:
9483 reg_kind = eRegisterKindGeneric;
9484 reg_num = LLDB_REGNUM_GENERIC_SP;
9485 break;
9486 case LR_REG:
9487 reg_kind = eRegisterKindGeneric;
9488 reg_num = LLDB_REGNUM_GENERIC_RA;
9489 break;
9490 default:
9491 reg_kind = eRegisterKindDWARF;
9492 reg_num = dwarf_r0 + Rd;
9493 }
9494 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00009495 return false;
9496 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00009497 return WriteFlags (context, result, carry, overflow);
9498 }
9499 return true;
9500}
9501
9502// This helper method tries to encapsulate the following pseudocode from the
9503// ARM Architecture Reference Manual:
9504//
9505// APSR.N = result<31>;
9506// APSR.Z = IsZeroBit(result);
9507// APSR.C = carry;
9508// APSR.V = overflow
9509//
9510// Default arguments can be specified for carry and overflow parameters, which means
9511// not to update the respective flags.
9512bool
9513EmulateInstructionARM::WriteFlags (Context &context,
9514 const uint32_t result,
9515 const uint32_t carry,
9516 const uint32_t overflow)
9517{
9518 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00009519 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
9520 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00009521 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009522 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00009523 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009524 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00009525 if (m_new_inst_cpsr != m_inst_cpsr)
9526 {
9527 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
9528 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00009529 }
9530 return true;
9531}
9532
Greg Clayton64c84432011-01-21 22:02:52 +00009533bool
9534EmulateInstructionARM::EvaluateInstruction ()
9535{
Johnny Chenc315f862011-02-05 00:46:10 +00009536 // Advance the ITSTATE bits to their values for the next instruction.
9537 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
9538 m_it_session.ITAdvance();
9539
Greg Clayton64c84432011-01-21 22:02:52 +00009540 return false;
9541}