blob: 540349e12a4fc0c5d57fdae1e27c3ec63a7a80d7 [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 Chen1c13b622011-01-29 00:11:15 +0000635 default:
636 return false;
637 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000638 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000639 if (!success)
640 return false;
641
642 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000643 EmulateInstruction::Context context;
644 context.type = EmulateInstruction::eContextRegisterPlusOffset;
645 Register dwarf_reg;
646 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
647 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000648
Johnny Chen10530c22011-02-17 22:37:12 +0000649 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000650 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000651 }
652 return true;
653}
654
Johnny Chen357c30f2011-02-14 22:04:25 +0000655// Move (immediate) writes an immediate value to the destination register. It
656// can optionally update the condition flags based on the value.
657// MOV (immediate)
658bool
Johnny Chen9f687722011-02-18 00:02:28 +0000659EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000660{
661#if 0
662 // ARM pseudo code...
663 if (ConditionPassed())
664 {
665 EncodingSpecificOperations();
666 result = imm32;
667 if d == 15 then // Can only occur for ARM encoding
668 ALUWritePC(result); // setflags is always FALSE here
669 else
670 R[d] = result;
671 if setflags then
672 APSR.N = result<31>;
673 APSR.Z = IsZeroBit(result);
674 APSR.C = carry;
675 // APSR.V unchanged
676 }
677#endif
678 bool success = false;
679 const uint32_t opcode = OpcodeAsUnsigned (&success);
680 if (!success)
681 return false;
682
683 if (ConditionPassed())
684 {
685 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000686 uint32_t imm32; // the immediate value to be written to Rd
687 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
688 bool setflags;
689 switch (encoding) {
690 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000691 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000692 setflags = !InITBlock();
693 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000694 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000695 break;
696 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000697 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000698 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000699 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000700 if (BadReg(Rd))
701 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000702 break;
703 default:
704 return false;
705 }
706 uint32_t result = imm32;
707
708 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000709 EmulateInstruction::Context context;
710 context.type = EmulateInstruction::eContextImmediate;
711 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000712
Johnny Chen10530c22011-02-17 22:37:12 +0000713 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000714 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000715 }
716 return true;
717}
718
Johnny Chend642a6a2011-02-22 01:01:03 +0000719// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
720// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000721bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000722EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000723{
724#if 0
725 // ARM pseudo code...
726 if (ConditionPassed())
727 {
728 EncodingSpecificOperations();
729 result = NOT(imm32);
730 if d == 15 then // Can only occur for ARM encoding
731 ALUWritePC(result); // setflags is always FALSE here
732 else
733 R[d] = result;
734 if setflags then
735 APSR.N = result<31>;
736 APSR.Z = IsZeroBit(result);
737 APSR.C = carry;
738 // APSR.V unchanged
739 }
740#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000741 bool success = false;
742 const uint32_t opcode = OpcodeAsUnsigned (&success);
743 if (!success)
744 return false;
745
746 if (ConditionPassed())
747 {
748 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000749 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
750 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000751 bool setflags;
752 switch (encoding) {
753 case eEncodingT1:
754 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000755 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000756 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000757 break;
758 case eEncodingA1:
759 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000760 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000761 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
762 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
763 // TODO: Emulate SUBS PC, LR and related instructions.
764 if (Rd == 15 && setflags)
765 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000766 break;
767 default:
768 return false;
769 }
770 uint32_t result = ~imm32;
771
772 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000773 EmulateInstruction::Context context;
774 context.type = EmulateInstruction::eContextImmediate;
775 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000776
Johnny Chen10530c22011-02-17 22:37:12 +0000777 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000778 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000779 }
780 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000781}
782
Johnny Chend642a6a2011-02-22 01:01:03 +0000783// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
784// It can optionally update the condition flags based on the result.
785bool
786EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
787{
788#if 0
789 // ARM pseudo code...
790 if (ConditionPassed())
791 {
792 EncodingSpecificOperations();
793 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
794 result = NOT(shifted);
795 if d == 15 then // Can only occur for ARM encoding
796 ALUWritePC(result); // setflags is always FALSE here
797 else
798 R[d] = result;
799 if setflags then
800 APSR.N = result<31>;
801 APSR.Z = IsZeroBit(result);
802 APSR.C = carry;
803 // APSR.V unchanged
804 }
805#endif
806
807 bool success = false;
808 const uint32_t opcode = OpcodeAsUnsigned (&success);
809 if (!success)
810 return false;
811
812 if (ConditionPassed())
813 {
814 uint32_t Rm; // the source register
815 uint32_t Rd; // the destination register
816 ARM_ShifterType shift_t;
817 uint32_t shift_n; // the shift applied to the value read from Rm
818 bool setflags;
819 uint32_t carry; // the carry bit after the shift operation
820 switch (encoding) {
821 case eEncodingT1:
822 Rd = Bits32(opcode, 2, 0);
823 Rm = Bits32(opcode, 5, 3);
824 setflags = !InITBlock();
825 shift_t = SRType_LSL;
826 shift_n = 0;
827 if (InITBlock())
828 return false;
829 break;
830 case eEncodingT2:
831 Rd = Bits32(opcode, 11, 8);
832 Rm = Bits32(opcode, 3, 0);
833 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000834 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000835 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000836 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000837 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000838 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000839 case eEncodingA1:
840 Rd = Bits32(opcode, 15, 12);
841 Rm = Bits32(opcode, 3, 0);
842 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000843 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000844 break;
845 default:
846 return false;
847 }
848 uint32_t value = ReadCoreReg(Rm, &success);
849 if (!success)
850 return false;
851
852 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
853 uint32_t result = ~shifted;
854
855 // The context specifies that an immediate is to be moved into Rd.
856 EmulateInstruction::Context context;
857 context.type = EmulateInstruction::eContextImmediate;
858 context.SetNoArgs ();
859
860 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
861 return false;
862 }
863 return true;
864}
865
Johnny Chen788e0552011-01-27 22:52:23 +0000866// PC relative immediate load into register, possibly followed by ADD (SP plus register).
867// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000868bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000869EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000870{
871#if 0
872 // ARM pseudo code...
873 if (ConditionPassed())
874 {
875 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
876 base = Align(PC,4);
877 address = if add then (base + imm32) else (base - imm32);
878 data = MemU[address,4];
879 if t == 15 then
880 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
881 elsif UnalignedSupport() || address<1:0> = ‘00’ then
882 R[t] = data;
883 else // Can only apply before ARMv7
884 if CurrentInstrSet() == InstrSet_ARM then
885 R[t] = ROR(data, 8*UInt(address<1:0>));
886 else
887 R[t] = bits(32) UNKNOWN;
888 }
889#endif
890
891 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000892 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000893 if (!success)
894 return false;
895
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000896 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000897 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000898 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000899 if (!success)
900 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000901
902 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000903 EmulateInstruction::Context context;
904 context.type = EmulateInstruction::eContextRegisterPlusOffset;
905 Register pc_reg;
906 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
907 context.SetRegisterPlusOffset (pc_reg, 0);
908
Johnny Chenc9de9102011-02-11 19:12:30 +0000909 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000910 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000911 bool add; // +imm32 or -imm32?
912 addr_t base; // the base address
913 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000914 uint32_t data; // the literal data value from the PC relative load
915 switch (encoding) {
916 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000917 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000918 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000919 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000920 break;
921 case eEncodingT2:
922 Rt = Bits32(opcode, 15, 12);
923 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
924 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000925 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000926 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000927 break;
928 default:
929 return false;
930 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000931
Johnny Chene39f22d2011-02-19 01:36:13 +0000932 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000933 if (add)
934 address = base + imm32;
935 else
936 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000937
938 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000939 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000940 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000941 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000942
943 if (Rt == 15)
944 {
945 if (Bits32(address, 1, 0) == 0)
946 {
947 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000948 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000949 return false;
950 }
951 else
952 return false;
953 }
954 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
955 {
956 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
957 return false;
958 }
959 else // We don't handle ARM for now.
960 return false;
961
962 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000963 return false;
964 }
965 return true;
966}
967
Johnny Chen5b442b72011-01-27 19:34:30 +0000968// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000969// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000970bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000971EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000972{
973#if 0
974 // ARM pseudo code...
975 if (ConditionPassed())
976 {
977 EncodingSpecificOperations();
978 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
979 if d == 15 then // Can only occur for ARM encoding
980 ALUWritePC(result); // setflags is always FALSE here
981 else
982 R[d] = result;
983 if setflags then
984 APSR.N = result<31>;
985 APSR.Z = IsZeroBit(result);
986 APSR.C = carry;
987 APSR.V = overflow;
988 }
989#endif
990
991 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000992 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000993 if (!success)
994 return false;
995
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000996 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000997 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000998 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000999 if (!success)
1000 return false;
1001 uint32_t imm32; // the immediate operand
1002 switch (encoding) {
1003 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001004 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001005 break;
1006 default:
1007 return false;
1008 }
1009 addr_t sp_offset = imm32;
1010 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1011
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001012 EmulateInstruction::Context context;
1013 context.type = EmulateInstruction::eContextAdjustStackPointer;
1014 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001015
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001016 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001017 return false;
1018 }
1019 return true;
1020}
1021
1022// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001023// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001024bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001025EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001026{
1027#if 0
1028 // ARM pseudo code...
1029 if (ConditionPassed())
1030 {
1031 EncodingSpecificOperations();
1032 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1033 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1034 if d == 15 then
1035 ALUWritePC(result); // setflags is always FALSE here
1036 else
1037 R[d] = result;
1038 if setflags then
1039 APSR.N = result<31>;
1040 APSR.Z = IsZeroBit(result);
1041 APSR.C = carry;
1042 APSR.V = overflow;
1043 }
1044#endif
1045
1046 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001047 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001048 if (!success)
1049 return false;
1050
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001051 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001052 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001053 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001054 if (!success)
1055 return false;
1056 uint32_t Rm; // the second operand
1057 switch (encoding) {
1058 case eEncodingT2:
1059 Rm = Bits32(opcode, 6, 3);
1060 break;
1061 default:
1062 return false;
1063 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001064 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001065 if (!success)
1066 return false;
1067
1068 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1069
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001070 EmulateInstruction::Context context;
1071 context.type = EmulateInstruction::eContextAdjustStackPointer;
1072 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001073
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001074 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001075 return false;
1076 }
1077 return true;
1078}
1079
Johnny Chen9b8d7832011-02-02 01:13:56 +00001080// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1081// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1082// from Thumb to ARM.
1083// BLX (immediate)
1084bool
1085EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1086{
1087#if 0
1088 // ARM pseudo code...
1089 if (ConditionPassed())
1090 {
1091 EncodingSpecificOperations();
1092 if CurrentInstrSet() == InstrSet_ARM then
1093 LR = PC - 4;
1094 else
1095 LR = PC<31:1> : '1';
1096 if targetInstrSet == InstrSet_ARM then
1097 targetAddress = Align(PC,4) + imm32;
1098 else
1099 targetAddress = PC + imm32;
1100 SelectInstrSet(targetInstrSet);
1101 BranchWritePC(targetAddress);
1102 }
1103#endif
1104
1105 bool success = false;
1106 const uint32_t opcode = OpcodeAsUnsigned (&success);
1107 if (!success)
1108 return false;
1109
1110 if (ConditionPassed())
1111 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001112 EmulateInstruction::Context context;
1113 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001114 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001115 if (!success)
1116 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001117 addr_t lr; // next instruction address
1118 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001119 int32_t imm32; // PC-relative offset
1120 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001121 case eEncodingT1:
1122 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001123 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001124 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001125 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001126 uint32_t J1 = Bit32(opcode, 13);
1127 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001128 uint32_t imm11 = Bits32(opcode, 10, 0);
1129 uint32_t I1 = !(J1 ^ S);
1130 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001131 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001132 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001133 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001134 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001135 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001136 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001137 break;
1138 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001139 case eEncodingT2:
1140 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001141 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001142 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001143 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001144 uint32_t J1 = Bit32(opcode, 13);
1145 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001146 uint32_t imm10L = Bits32(opcode, 10, 1);
1147 uint32_t I1 = !(J1 ^ S);
1148 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001149 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001150 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001151 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001152 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001153 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001154 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001155 break;
1156 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001157 case eEncodingA1:
1158 lr = pc + 4; // return address
1159 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001160 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001161 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001162 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001163 case eEncodingA2:
1164 lr = pc + 4; // return address
1165 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001166 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001167 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001168 break;
1169 default:
1170 return false;
1171 }
1172 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1173 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001174 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001175 return false;
1176 }
1177 return true;
1178}
1179
1180// Branch with Link and Exchange (register) calls a subroutine at an address and
1181// instruction set specified by a register.
1182// BLX (register)
1183bool
1184EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1185{
1186#if 0
1187 // ARM pseudo code...
1188 if (ConditionPassed())
1189 {
1190 EncodingSpecificOperations();
1191 target = R[m];
1192 if CurrentInstrSet() == InstrSet_ARM then
1193 next_instr_addr = PC - 4;
1194 LR = next_instr_addr;
1195 else
1196 next_instr_addr = PC - 2;
1197 LR = next_instr_addr<31:1> : ‘1’;
1198 BXWritePC(target);
1199 }
1200#endif
1201
1202 bool success = false;
1203 const uint32_t opcode = OpcodeAsUnsigned (&success);
1204 if (!success)
1205 return false;
1206
1207 if (ConditionPassed())
1208 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001209 EmulateInstruction::Context context;
1210 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001211 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001212 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001213 if (!success)
1214 return false;
1215 uint32_t Rm; // the register with the target address
1216 switch (encoding) {
1217 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001218 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001219 Rm = Bits32(opcode, 6, 3);
1220 // if m == 15 then UNPREDICTABLE;
1221 if (Rm == 15)
1222 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001223 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001224 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001225 break;
1226 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001227 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001228 Rm = Bits32(opcode, 3, 0);
1229 // if m == 15 then UNPREDICTABLE;
1230 if (Rm == 15)
1231 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001232 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001233 default:
1234 return false;
1235 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001236 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001237 if (!success)
1238 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001239 Register dwarf_reg;
1240 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1241 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001242 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1243 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001244 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001245 return false;
1246 }
1247 return true;
1248}
1249
Johnny Chenab3b3512011-02-12 00:10:51 +00001250// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001251bool
1252EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1253{
1254#if 0
1255 // ARM pseudo code...
1256 if (ConditionPassed())
1257 {
1258 EncodingSpecificOperations();
1259 BXWritePC(R[m]);
1260 }
1261#endif
1262
1263 bool success = false;
1264 const uint32_t opcode = OpcodeAsUnsigned (&success);
1265 if (!success)
1266 return false;
1267
1268 if (ConditionPassed())
1269 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001270 EmulateInstruction::Context context;
1271 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001272 uint32_t Rm; // the register with the target address
1273 switch (encoding) {
1274 case eEncodingT1:
1275 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001276 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001277 return false;
1278 break;
1279 case eEncodingA1:
1280 Rm = Bits32(opcode, 3, 0);
1281 break;
1282 default:
1283 return false;
1284 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001285 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001286 if (!success)
1287 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001288
1289 Register dwarf_reg;
1290 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001291 context.SetRegister (dwarf_reg);
1292 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001293 return false;
1294 }
1295 return true;
1296}
1297
Johnny Chen59e6ab72011-02-24 21:01:20 +00001298// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1299// address and instruction set specified by a register as though it were a BX instruction.
1300//
1301// TODO: Emulate Jazelle architecture?
1302// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1303bool
1304EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1305{
1306#if 0
1307 // ARM pseudo code...
1308 if (ConditionPassed())
1309 {
1310 EncodingSpecificOperations();
1311 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1312 BXWritePC(R[m]);
1313 else
1314 if JazelleAcceptsExecution() then
1315 SwitchToJazelleExecution();
1316 else
1317 SUBARCHITECTURE_DEFINED handler call;
1318 }
1319#endif
1320
1321 bool success = false;
1322 const uint32_t opcode = OpcodeAsUnsigned (&success);
1323 if (!success)
1324 return false;
1325
1326 if (ConditionPassed())
1327 {
1328 EmulateInstruction::Context context;
1329 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1330 uint32_t Rm; // the register with the target address
1331 switch (encoding) {
1332 case eEncodingT1:
1333 Rm = Bits32(opcode, 19, 16);
1334 if (BadReg(Rm))
1335 return false;
1336 if (InITBlock() && !LastInITBlock())
1337 return false;
1338 break;
1339 case eEncodingA1:
1340 Rm = Bits32(opcode, 3, 0);
1341 if (Rm == 15)
1342 return false;
1343 break;
1344 default:
1345 return false;
1346 }
1347 addr_t target = ReadCoreReg (Rm, &success);
1348 if (!success)
1349 return false;
1350
1351 Register dwarf_reg;
1352 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1353 context.SetRegister (dwarf_reg);
1354 if (!BXWritePC(context, target))
1355 return false;
1356 }
1357 return true;
1358}
1359
Johnny Chen0d0148e2011-01-28 02:26:08 +00001360// Set r7 to point to some ip offset.
1361// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001362bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001363EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001364{
1365#if 0
1366 // ARM pseudo code...
1367 if (ConditionPassed())
1368 {
1369 EncodingSpecificOperations();
1370 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1371 if d == 15 then // Can only occur for ARM encoding
1372 ALUWritePC(result); // setflags is always FALSE here
1373 else
1374 R[d] = result;
1375 if setflags then
1376 APSR.N = result<31>;
1377 APSR.Z = IsZeroBit(result);
1378 APSR.C = carry;
1379 APSR.V = overflow;
1380 }
1381#endif
1382
1383 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001384 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001385 if (!success)
1386 return false;
1387
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001388 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001389 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001390 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001391 if (!success)
1392 return false;
1393 uint32_t imm32;
1394 switch (encoding) {
1395 case eEncodingA1:
1396 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1397 break;
1398 default:
1399 return false;
1400 }
1401 addr_t ip_offset = imm32;
1402 addr_t addr = ip - ip_offset; // the adjusted ip value
1403
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001404 EmulateInstruction::Context context;
1405 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1406 Register dwarf_reg;
1407 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1408 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001409
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001410 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001411 return false;
1412 }
1413 return true;
1414}
1415
1416// Set ip to point to some stack offset.
1417// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001418bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001419EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001420{
1421#if 0
1422 // ARM pseudo code...
1423 if (ConditionPassed())
1424 {
1425 EncodingSpecificOperations();
1426 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1427 if d == 15 then // Can only occur for ARM encoding
1428 ALUWritePC(result); // setflags is always FALSE here
1429 else
1430 R[d] = result;
1431 if setflags then
1432 APSR.N = result<31>;
1433 APSR.Z = IsZeroBit(result);
1434 APSR.C = carry;
1435 APSR.V = overflow;
1436 }
1437#endif
1438
1439 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001440 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001441 if (!success)
1442 return false;
1443
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001444 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001445 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001446 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001447 if (!success)
1448 return false;
1449 uint32_t imm32;
1450 switch (encoding) {
1451 case eEncodingA1:
1452 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1453 break;
1454 default:
1455 return false;
1456 }
1457 addr_t sp_offset = imm32;
1458 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1459
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001460 EmulateInstruction::Context context;
1461 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1462 Register dwarf_reg;
1463 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1464 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001465
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001466 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001467 return false;
1468 }
1469 return true;
1470}
1471
Johnny Chenc9e747f2011-02-23 01:55:07 +00001472// This instruction subtracts an immediate value from the SP value, and writes
1473// the result to the destination register.
1474//
1475// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001476bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001477EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001478{
1479#if 0
1480 // ARM pseudo code...
1481 if (ConditionPassed())
1482 {
1483 EncodingSpecificOperations();
1484 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001485 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001486 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001487 else
1488 R[d] = result;
1489 if setflags then
1490 APSR.N = result<31>;
1491 APSR.Z = IsZeroBit(result);
1492 APSR.C = carry;
1493 APSR.V = overflow;
1494 }
1495#endif
1496
1497 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001498 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001499 if (!success)
1500 return false;
1501
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001502 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001503 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001504 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001505 if (!success)
1506 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001507
1508 uint32_t Rd;
1509 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001510 uint32_t imm32;
1511 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001512 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001513 Rd = 13;
1514 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001515 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001516 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001517 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001518 Rd = Bits32(opcode, 11, 8);
1519 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001520 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001521 if (Rd == 15 && setflags)
1522 return EmulateCMPImm(eEncodingT2);
1523 if (Rd == 15 && !setflags)
1524 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001525 break;
1526 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001527 Rd = Bits32(opcode, 11, 8);
1528 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001529 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001530 if (Rd == 15)
1531 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001532 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001533 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001534 Rd = Bits32(opcode, 15, 12);
1535 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001536 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001537 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1538 // TODO: Emulate SUBS PC, LR and related instructions.
1539 if (Rd == 15 && setflags)
1540 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001541 break;
1542 default:
1543 return false;
1544 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001545 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1546
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001547 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001548 if (Rd == 13)
1549 {
1550 context.type = EmulateInstruction::eContextAdjustStackPointer;
1551 context.SetImmediateSigned (-imm32); // the stack pointer offset
1552 }
1553 else
1554 {
1555 context.type = EmulateInstruction::eContextImmediate;
1556 context.SetNoArgs ();
1557 }
1558
1559 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001560 return false;
1561 }
1562 return true;
1563}
1564
Johnny Chen08c25e82011-01-31 18:02:28 +00001565// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001566bool
1567EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001568{
1569#if 0
1570 // ARM pseudo code...
1571 if (ConditionPassed())
1572 {
1573 EncodingSpecificOperations();
1574 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1575 address = if index then offset_addr else R[n];
1576 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1577 if wback then R[n] = offset_addr;
1578 }
1579#endif
1580
1581 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001582 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001583 if (!success)
1584 return false;
1585
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001586 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001587 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001589 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001590 if (!success)
1591 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001592 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001593 uint32_t imm12;
1594 switch (encoding) {
1595 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001596 Rt = Bits32(opcode, 15, 12);
1597 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001598 break;
1599 default:
1600 return false;
1601 }
1602 addr_t sp_offset = imm12;
1603 addr_t addr = sp - sp_offset;
1604
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001605 EmulateInstruction::Context context;
1606 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1607 Register dwarf_reg;
1608 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001609 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001610 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001611 dwarf_reg.num = dwarf_r0 + Rt;
1612 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001613 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001614 if (!success)
1615 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001616 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001617 return false;
1618 }
1619 else
1620 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001621 dwarf_reg.num = dwarf_pc;
1622 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001623 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001624 if (!success)
1625 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001626 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001627 return false;
1628 }
1629
1630 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001631 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001632
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001633 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001634 return false;
1635 }
1636 return true;
1637}
1638
Johnny Chen08c25e82011-01-31 18:02:28 +00001639// Vector Push stores multiple extension registers to the stack.
1640// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641bool
1642EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1649 address = SP - imm32;
1650 SP = SP - imm32;
1651 if single_regs then
1652 for r = 0 to regs-1
1653 MemA[address,4] = S[d+r]; address = address+4;
1654 else
1655 for r = 0 to regs-1
1656 // Store as two word-aligned words in the correct order for current endianness.
1657 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1658 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1659 address = address+8;
1660 }
1661#endif
1662
1663 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001664 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001665 if (!success)
1666 return false;
1667
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001668 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001669 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001670 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001671 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001672 if (!success)
1673 return false;
1674 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001675 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001676 uint32_t imm32; // stack offset
1677 uint32_t regs; // number of registers
1678 switch (encoding) {
1679 case eEncodingT1:
1680 case eEncodingA1:
1681 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001682 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001683 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1684 // If UInt(imm8) is odd, see "FSTMX".
1685 regs = Bits32(opcode, 7, 0) / 2;
1686 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1687 if (regs == 0 || regs > 16 || (d + regs) > 32)
1688 return false;
1689 break;
1690 case eEncodingT2:
1691 case eEncodingA2:
1692 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001693 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001694 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1695 regs = Bits32(opcode, 7, 0);
1696 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1697 if (regs == 0 || regs > 16 || (d + regs) > 32)
1698 return false;
1699 break;
1700 default:
1701 return false;
1702 }
1703 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1704 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1705 addr_t sp_offset = imm32;
1706 addr_t addr = sp - sp_offset;
1707 uint32_t i;
1708
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001709 EmulateInstruction::Context context;
1710 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1711 Register dwarf_reg;
1712 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001713 for (i=d; i<regs; ++i)
1714 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001715 dwarf_reg.num = start_reg + i;
1716 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001717 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001718 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001719 if (!success)
1720 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001721 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001722 return false;
1723 addr += reg_byte_size;
1724 }
1725
1726 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001727 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001728
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001729 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001730 return false;
1731 }
1732 return true;
1733}
1734
Johnny Chen587a0a42011-02-01 18:35:28 +00001735// Vector Pop loads multiple extension registers from the stack.
1736// It also updates SP to point just above the loaded data.
1737bool
1738EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1739{
1740#if 0
1741 // ARM pseudo code...
1742 if (ConditionPassed())
1743 {
1744 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1745 address = SP;
1746 SP = SP + imm32;
1747 if single_regs then
1748 for r = 0 to regs-1
1749 S[d+r] = MemA[address,4]; address = address+4;
1750 else
1751 for r = 0 to regs-1
1752 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1753 // Combine the word-aligned words in the correct order for current endianness.
1754 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1755 }
1756#endif
1757
1758 bool success = false;
1759 const uint32_t opcode = OpcodeAsUnsigned (&success);
1760 if (!success)
1761 return false;
1762
1763 if (ConditionPassed())
1764 {
1765 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001766 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001767 if (!success)
1768 return false;
1769 bool single_regs;
1770 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1771 uint32_t imm32; // stack offset
1772 uint32_t regs; // number of registers
1773 switch (encoding) {
1774 case eEncodingT1:
1775 case eEncodingA1:
1776 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001777 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001778 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1779 // If UInt(imm8) is odd, see "FLDMX".
1780 regs = Bits32(opcode, 7, 0) / 2;
1781 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1782 if (regs == 0 || regs > 16 || (d + regs) > 32)
1783 return false;
1784 break;
1785 case eEncodingT2:
1786 case eEncodingA2:
1787 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001788 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001789 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1790 regs = Bits32(opcode, 7, 0);
1791 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1792 if (regs == 0 || regs > 16 || (d + regs) > 32)
1793 return false;
1794 break;
1795 default:
1796 return false;
1797 }
1798 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1799 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1800 addr_t sp_offset = imm32;
1801 addr_t addr = sp;
1802 uint32_t i;
1803 uint64_t data; // uint64_t to accomodate 64-bit registers.
1804
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001805 EmulateInstruction::Context context;
1806 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1807 Register dwarf_reg;
1808 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001809 for (i=d; i<regs; ++i)
1810 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001811 dwarf_reg.num = start_reg + i;
1812 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001813 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001814 if (!success)
1815 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001816 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001817 return false;
1818 addr += reg_byte_size;
1819 }
1820
1821 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001822 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001823
1824 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1825 return false;
1826 }
1827 return true;
1828}
1829
Johnny Chenb77be412011-02-04 00:40:18 +00001830// SVC (previously SWI)
1831bool
1832EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1833{
1834#if 0
1835 // ARM pseudo code...
1836 if (ConditionPassed())
1837 {
1838 EncodingSpecificOperations();
1839 CallSupervisor();
1840 }
1841#endif
1842
1843 bool success = false;
1844 const uint32_t opcode = OpcodeAsUnsigned (&success);
1845 if (!success)
1846 return false;
1847
1848 if (ConditionPassed())
1849 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001850 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001851 addr_t lr; // next instruction address
1852 if (!success)
1853 return false;
1854 uint32_t imm32; // the immediate constant
1855 uint32_t mode; // ARM or Thumb mode
1856 switch (encoding) {
1857 case eEncodingT1:
1858 lr = (pc + 2) | 1u; // return address
1859 imm32 = Bits32(opcode, 7, 0);
1860 mode = eModeThumb;
1861 break;
1862 case eEncodingA1:
1863 lr = pc + 4; // return address
1864 imm32 = Bits32(opcode, 23, 0);
1865 mode = eModeARM;
1866 break;
1867 default:
1868 return false;
1869 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001870
1871 EmulateInstruction::Context context;
1872 context.type = EmulateInstruction::eContextSupervisorCall;
1873 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001874 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1875 return false;
1876 }
1877 return true;
1878}
1879
Johnny Chenc315f862011-02-05 00:46:10 +00001880// If Then makes up to four following instructions (the IT block) conditional.
1881bool
1882EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1883{
1884#if 0
1885 // ARM pseudo code...
1886 EncodingSpecificOperations();
1887 ITSTATE.IT<7:0> = firstcond:mask;
1888#endif
1889
1890 bool success = false;
1891 const uint32_t opcode = OpcodeAsUnsigned (&success);
1892 if (!success)
1893 return false;
1894
1895 m_it_session.InitIT(Bits32(opcode, 7, 0));
1896 return true;
1897}
1898
Johnny Chen3b620b32011-02-07 20:11:47 +00001899// Branch causes a branch to a target address.
1900bool
1901EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1902{
1903#if 0
1904 // ARM pseudo code...
1905 if (ConditionPassed())
1906 {
1907 EncodingSpecificOperations();
1908 BranchWritePC(PC + imm32);
1909 }
1910#endif
1911
1912 bool success = false;
1913 const uint32_t opcode = OpcodeAsUnsigned (&success);
1914 if (!success)
1915 return false;
1916
Johnny Chen9ee056b2011-02-08 00:06:35 +00001917 if (ConditionPassed())
1918 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001919 EmulateInstruction::Context context;
1920 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001921 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001922 if (!success)
1923 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001924 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001925 int32_t imm32; // PC-relative offset
1926 switch (encoding) {
1927 case eEncodingT1:
1928 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1929 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001930 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001931 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001932 break;
1933 case eEncodingT2:
1934 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001935 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001936 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001937 break;
1938 case eEncodingT3:
1939 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1940 {
Johnny Chenbd599902011-02-10 21:39:01 +00001941 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001942 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001943 uint32_t J1 = Bit32(opcode, 13);
1944 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001945 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001946 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001947 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001948 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001949 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001950 break;
1951 }
1952 case eEncodingT4:
1953 {
Johnny Chenbd599902011-02-10 21:39:01 +00001954 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001955 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001956 uint32_t J1 = Bit32(opcode, 13);
1957 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001958 uint32_t imm11 = Bits32(opcode, 10, 0);
1959 uint32_t I1 = !(J1 ^ S);
1960 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001961 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001962 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001963 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001964 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001965 break;
1966 }
1967 case eEncodingA1:
1968 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001969 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001970 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001971 break;
1972 default:
1973 return false;
1974 }
1975 if (!BranchWritePC(context, target))
1976 return false;
1977 }
1978 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001979}
1980
Johnny Chen53ebab72011-02-08 23:21:57 +00001981// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1982// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1983// CBNZ, CBZ
1984bool
1985EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1986{
1987#if 0
1988 // ARM pseudo code...
1989 EncodingSpecificOperations();
1990 if nonzero ^ IsZero(R[n]) then
1991 BranchWritePC(PC + imm32);
1992#endif
1993
1994 bool success = false;
1995 const uint32_t opcode = OpcodeAsUnsigned (&success);
1996 if (!success)
1997 return false;
1998
1999 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002000 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002001 if (!success)
2002 return false;
2003
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002004 EmulateInstruction::Context context;
2005 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002006 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002007 if (!success)
2008 return false;
2009
2010 addr_t target; // target address
2011 uint32_t imm32; // PC-relative offset to branch forward
2012 bool nonzero;
2013 switch (encoding) {
2014 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002015 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002016 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002017 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002018 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002019 break;
2020 default:
2021 return false;
2022 }
2023 if (nonzero ^ (reg_val == 0))
2024 if (!BranchWritePC(context, target))
2025 return false;
2026
2027 return true;
2028}
2029
Johnny Chen60299ec2011-02-17 19:34:27 +00002030// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2031// A base register provides a pointer to the table, and a second register supplies an index into the table.
2032// The branch length is twice the value of the byte returned from the table.
2033//
2034// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2035// A base register provides a pointer to the table, and a second register supplies an index into the table.
2036// The branch length is twice the value of the halfword returned from the table.
2037// TBB, TBH
2038bool
2039EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2040{
2041#if 0
2042 // ARM pseudo code...
2043 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2044 if is_tbh then
2045 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2046 else
2047 halfwords = UInt(MemU[R[n]+R[m], 1]);
2048 BranchWritePC(PC + 2*halfwords);
2049#endif
2050
2051 bool success = false;
2052 const uint32_t opcode = OpcodeAsUnsigned (&success);
2053 if (!success)
2054 return false;
2055
2056 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2057 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2058 bool is_tbh; // true if table branch halfword
2059 switch (encoding) {
2060 case eEncodingT1:
2061 Rn = Bits32(opcode, 19, 16);
2062 Rm = Bits32(opcode, 3, 0);
2063 is_tbh = BitIsSet(opcode, 4);
2064 if (Rn == 13 || BadReg(Rm))
2065 return false;
2066 if (InITBlock() && !LastInITBlock())
2067 return false;
2068 break;
2069 default:
2070 return false;
2071 }
2072
2073 // Read the address of the table from the operand register Rn.
2074 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002075 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002076 if (!success)
2077 return false;
2078
2079 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002080 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002081 if (!success)
2082 return false;
2083
2084 // the offsetted table address
2085 addr_t addr = base + (is_tbh ? index*2 : index);
2086
2087 // PC-relative offset to branch forward
2088 EmulateInstruction::Context context;
2089 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002090 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002091 if (!success)
2092 return false;
2093
Johnny Chene39f22d2011-02-19 01:36:13 +00002094 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002095 if (!success)
2096 return false;
2097
2098 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002099 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002100 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2101 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2102
2103 if (!BranchWritePC(context, target))
2104 return false;
2105
2106 return true;
2107}
2108
Johnny Chen8fa20592011-02-18 01:22:22 +00002109// This instruction adds an immediate value to a register value, and writes the result to the destination
2110// register. It can optionally update the condition flags based on the result.
2111bool
2112EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2113{
2114#if 0
2115 // ARM pseudo code...
2116 if ConditionPassed() then
2117 EncodingSpecificOperations();
2118 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2119 if d == 15 then
2120 ALUWritePC(result); // setflags is always FALSE here
2121 else
2122 R[d] = result;
2123 if setflags then
2124 APSR.N = result<31>;
2125 APSR.Z = IsZeroBit(result);
2126 APSR.C = carry;
2127 APSR.V = overflow;
2128#endif
2129
2130 bool success = false;
2131 const uint32_t opcode = OpcodeAsUnsigned (&success);
2132 if (!success)
2133 return false;
2134
2135 if (ConditionPassed())
2136 {
2137 uint32_t Rd, Rn;
2138 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2139 bool setflags;
2140 switch (encoding)
2141 {
2142 case eEncodingA1:
2143 Rd = Bits32(opcode, 15, 12);
2144 Rn = Bits32(opcode, 19, 16);
2145 setflags = BitIsSet(opcode, 20);
2146 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2147 break;
2148 default:
2149 return false;
2150 }
2151
Johnny Chen8fa20592011-02-18 01:22:22 +00002152 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002153 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002154 if (!success)
2155 return false;
2156
2157 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2158
2159 EmulateInstruction::Context context;
2160 context.type = EmulateInstruction::eContextImmediate;
2161 context.SetNoArgs ();
2162
2163 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2164 return false;
2165 }
2166 return true;
2167}
2168
Johnny Chend761dcf2011-02-17 22:03:29 +00002169// This instruction adds a register value and an optionally-shifted register value, and writes the result
2170// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002171bool
Johnny Chen9f687722011-02-18 00:02:28 +00002172EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002173{
2174#if 0
2175 // ARM pseudo code...
2176 if ConditionPassed() then
2177 EncodingSpecificOperations();
2178 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2179 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2180 if d == 15 then
2181 ALUWritePC(result); // setflags is always FALSE here
2182 else
2183 R[d] = result;
2184 if setflags then
2185 APSR.N = result<31>;
2186 APSR.Z = IsZeroBit(result);
2187 APSR.C = carry;
2188 APSR.V = overflow;
2189#endif
2190
2191 bool success = false;
2192 const uint32_t opcode = OpcodeAsUnsigned (&success);
2193 if (!success)
2194 return false;
2195
2196 if (ConditionPassed())
2197 {
2198 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002199 ARM_ShifterType shift_t;
2200 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002201 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002202 switch (encoding)
2203 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002204 case eEncodingT1:
2205 Rd = Bits32(opcode, 2, 0);
2206 Rn = Bits32(opcode, 5, 3);
2207 Rm = Bits32(opcode, 8, 6);
2208 setflags = !InITBlock();
2209 shift_t = SRType_LSL;
2210 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002211 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002212 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002213 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002214 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002215 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002216 shift_t = SRType_LSL;
2217 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002218 if (Rn == 15 && Rm == 15)
2219 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002220 if (Rd == 15 && InITBlock() && !LastInITBlock())
2221 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002222 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002223 case eEncodingA1:
2224 Rd = Bits32(opcode, 15, 12);
2225 Rn = Bits32(opcode, 19, 16);
2226 Rm = Bits32(opcode, 3, 0);
2227 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002228 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002229 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002230 default:
2231 return false;
2232 }
2233
Johnny Chen26863dc2011-02-09 23:43:29 +00002234 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002235 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002236 if (!success)
2237 return false;
2238
2239 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002240 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002241 if (!success)
2242 return false;
2243
Johnny Chene97c0d52011-02-18 19:32:20 +00002244 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002245 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002246
2247 EmulateInstruction::Context context;
2248 context.type = EmulateInstruction::eContextImmediate;
2249 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002250
Johnny Chen10530c22011-02-17 22:37:12 +00002251 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002252 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002253 }
2254 return true;
2255}
2256
Johnny Chen34075cb2011-02-22 01:56:31 +00002257// Compare Negative (immediate) adds a register value and an immediate value.
2258// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002259bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002260EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2261{
2262#if 0
2263 // ARM pseudo code...
2264 if ConditionPassed() then
2265 EncodingSpecificOperations();
2266 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2267 APSR.N = result<31>;
2268 APSR.Z = IsZeroBit(result);
2269 APSR.C = carry;
2270 APSR.V = overflow;
2271#endif
2272
2273 bool success = false;
2274 const uint32_t opcode = OpcodeAsUnsigned (&success);
2275 if (!success)
2276 return false;
2277
2278 uint32_t Rn; // the first operand
2279 uint32_t imm32; // the immediate value to be compared with
2280 switch (encoding) {
2281 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002282 Rn = Bits32(opcode, 19, 16);
2283 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2284 if (Rn == 15)
2285 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002286 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002287 case eEncodingA1:
2288 Rn = Bits32(opcode, 19, 16);
2289 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2290 break;
2291 default:
2292 return false;
2293 }
2294 // Read the register value from the operand register Rn.
2295 uint32_t reg_val = ReadCoreReg(Rn, &success);
2296 if (!success)
2297 return false;
2298
Johnny Chen078fbc62011-02-22 19:48:22 +00002299 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002300
2301 EmulateInstruction::Context context;
2302 context.type = EmulateInstruction::eContextImmediate;
2303 context.SetNoArgs ();
2304 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2305 return false;
2306
2307 return true;
2308}
2309
2310// Compare Negative (register) adds a register value and an optionally-shifted register value.
2311// It updates the condition flags based on the result, and discards the result.
2312bool
2313EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2314{
2315#if 0
2316 // ARM pseudo code...
2317 if ConditionPassed() then
2318 EncodingSpecificOperations();
2319 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2320 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2321 APSR.N = result<31>;
2322 APSR.Z = IsZeroBit(result);
2323 APSR.C = carry;
2324 APSR.V = overflow;
2325#endif
2326
2327 bool success = false;
2328 const uint32_t opcode = OpcodeAsUnsigned (&success);
2329 if (!success)
2330 return false;
2331
2332 uint32_t Rn; // the first operand
2333 uint32_t Rm; // the second operand
2334 ARM_ShifterType shift_t;
2335 uint32_t shift_n; // the shift applied to the value read from Rm
2336 switch (encoding) {
2337 case eEncodingT1:
2338 Rn = Bits32(opcode, 2, 0);
2339 Rm = Bits32(opcode, 5, 3);
2340 shift_t = SRType_LSL;
2341 shift_n = 0;
2342 break;
2343 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002344 Rn = Bits32(opcode, 19, 16);
2345 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002346 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002347 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2348 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002349 return false;
2350 break;
2351 case eEncodingA1:
2352 Rn = Bits32(opcode, 19, 16);
2353 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002354 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002355 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002356 default:
2357 return false;
2358 }
2359 // Read the register value from register Rn.
2360 uint32_t val1 = ReadCoreReg(Rn, &success);
2361 if (!success)
2362 return false;
2363
2364 // Read the register value from register Rm.
2365 uint32_t val2 = ReadCoreReg(Rm, &success);
2366 if (!success)
2367 return false;
2368
2369 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002370 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002371
2372 EmulateInstruction::Context context;
2373 context.type = EmulateInstruction::eContextImmediate;
2374 context.SetNoArgs();
2375 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2376 return false;
2377
2378 return true;
2379}
2380
2381// Compare (immediate) subtracts an immediate value from a register value.
2382// It updates the condition flags based on the result, and discards the result.
2383bool
2384EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002385{
2386#if 0
2387 // ARM pseudo code...
2388 if ConditionPassed() then
2389 EncodingSpecificOperations();
2390 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2391 APSR.N = result<31>;
2392 APSR.Z = IsZeroBit(result);
2393 APSR.C = carry;
2394 APSR.V = overflow;
2395#endif
2396
2397 bool success = false;
2398 const uint32_t opcode = OpcodeAsUnsigned (&success);
2399 if (!success)
2400 return false;
2401
2402 uint32_t Rn; // the first operand
2403 uint32_t imm32; // the immediate value to be compared with
2404 switch (encoding) {
2405 case eEncodingT1:
2406 Rn = Bits32(opcode, 10, 8);
2407 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002408 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002409 case eEncodingT2:
2410 Rn = Bits32(opcode, 19, 16);
2411 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2412 if (Rn == 15)
2413 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002414 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002415 case eEncodingA1:
2416 Rn = Bits32(opcode, 19, 16);
2417 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002418 break;
2419 default:
2420 return false;
2421 }
2422 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002423 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002424 if (!success)
2425 return false;
2426
Johnny Chen10530c22011-02-17 22:37:12 +00002427 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2428
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002429 EmulateInstruction::Context context;
2430 context.type = EmulateInstruction::eContextImmediate;
2431 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002432 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2433 return false;
2434
Johnny Chend4dc4442011-02-11 02:02:56 +00002435 return true;
2436}
2437
Johnny Chen34075cb2011-02-22 01:56:31 +00002438// Compare (register) subtracts an optionally-shifted register value from a register value.
2439// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002440bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002441EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002442{
2443#if 0
2444 // ARM pseudo code...
2445 if ConditionPassed() then
2446 EncodingSpecificOperations();
2447 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2448 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2449 APSR.N = result<31>;
2450 APSR.Z = IsZeroBit(result);
2451 APSR.C = carry;
2452 APSR.V = overflow;
2453#endif
2454
2455 bool success = false;
2456 const uint32_t opcode = OpcodeAsUnsigned (&success);
2457 if (!success)
2458 return false;
2459
2460 uint32_t Rn; // the first operand
2461 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002462 ARM_ShifterType shift_t;
2463 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002464 switch (encoding) {
2465 case eEncodingT1:
2466 Rn = Bits32(opcode, 2, 0);
2467 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002468 shift_t = SRType_LSL;
2469 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002470 break;
2471 case eEncodingT2:
2472 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2473 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002474 shift_t = SRType_LSL;
2475 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002476 if (Rn < 8 && Rm < 8)
2477 return false;
2478 if (Rn == 15 || Rm == 15)
2479 return false;
2480 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002481 case eEncodingA1:
2482 Rn = Bits32(opcode, 19, 16);
2483 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002484 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002485 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002486 default:
2487 return false;
2488 }
2489 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002490 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002491 if (!success)
2492 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002493
Johnny Chene4a4d302011-02-11 21:53:58 +00002494 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002495 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002496 if (!success)
2497 return false;
2498
Johnny Chen34075cb2011-02-22 01:56:31 +00002499 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2500 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002501
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002502 EmulateInstruction::Context context;
2503 context.type = EmulateInstruction::eContextImmediate;
2504 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002505 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2506 return false;
2507
Johnny Chene4a4d302011-02-11 21:53:58 +00002508 return true;
2509}
2510
Johnny Chen82f16aa2011-02-15 20:10:55 +00002511// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2512// shifting in copies of its sign bit, and writes the result to the destination register. It can
2513// optionally update the condition flags based on the result.
2514bool
2515EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2516{
2517#if 0
2518 // ARM pseudo code...
2519 if ConditionPassed() then
2520 EncodingSpecificOperations();
2521 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2522 if d == 15 then // Can only occur for ARM encoding
2523 ALUWritePC(result); // setflags is always FALSE here
2524 else
2525 R[d] = result;
2526 if setflags then
2527 APSR.N = result<31>;
2528 APSR.Z = IsZeroBit(result);
2529 APSR.C = carry;
2530 // APSR.V unchanged
2531#endif
2532
Johnny Chen41a0a152011-02-16 01:27:54 +00002533 return EmulateShiftImm(encoding, SRType_ASR);
2534}
2535
2536// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2537// shifting in copies of its sign bit, and writes the result to the destination register.
2538// The variable number of bits is read from the bottom byte of a register. It can optionally update
2539// the condition flags based on the result.
2540bool
2541EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2542{
2543#if 0
2544 // ARM pseudo code...
2545 if ConditionPassed() then
2546 EncodingSpecificOperations();
2547 shift_n = UInt(R[m]<7:0>);
2548 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2549 R[d] = result;
2550 if setflags then
2551 APSR.N = result<31>;
2552 APSR.Z = IsZeroBit(result);
2553 APSR.C = carry;
2554 // APSR.V unchanged
2555#endif
2556
2557 return EmulateShiftReg(encoding, SRType_ASR);
2558}
2559
2560// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2561// shifting in zeros, and writes the result to the destination register. It can optionally
2562// update the condition flags based on the result.
2563bool
2564EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2565{
2566#if 0
2567 // ARM pseudo code...
2568 if ConditionPassed() then
2569 EncodingSpecificOperations();
2570 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2571 if d == 15 then // Can only occur for ARM encoding
2572 ALUWritePC(result); // setflags is always FALSE here
2573 else
2574 R[d] = result;
2575 if setflags then
2576 APSR.N = result<31>;
2577 APSR.Z = IsZeroBit(result);
2578 APSR.C = carry;
2579 // APSR.V unchanged
2580#endif
2581
2582 return EmulateShiftImm(encoding, SRType_LSL);
2583}
2584
2585// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2586// shifting in zeros, and writes the result to the destination register. The variable number
2587// of bits is read from the bottom byte of a register. It can optionally update the condition
2588// flags based on the result.
2589bool
2590EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2591{
2592#if 0
2593 // ARM pseudo code...
2594 if ConditionPassed() then
2595 EncodingSpecificOperations();
2596 shift_n = UInt(R[m]<7:0>);
2597 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2598 R[d] = result;
2599 if setflags then
2600 APSR.N = result<31>;
2601 APSR.Z = IsZeroBit(result);
2602 APSR.C = carry;
2603 // APSR.V unchanged
2604#endif
2605
2606 return EmulateShiftReg(encoding, SRType_LSL);
2607}
2608
2609// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2610// shifting in zeros, and writes the result to the destination register. It can optionally
2611// update the condition flags based on the result.
2612bool
2613EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2614{
2615#if 0
2616 // ARM pseudo code...
2617 if ConditionPassed() then
2618 EncodingSpecificOperations();
2619 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2620 if d == 15 then // Can only occur for ARM encoding
2621 ALUWritePC(result); // setflags is always FALSE here
2622 else
2623 R[d] = result;
2624 if setflags then
2625 APSR.N = result<31>;
2626 APSR.Z = IsZeroBit(result);
2627 APSR.C = carry;
2628 // APSR.V unchanged
2629#endif
2630
2631 return EmulateShiftImm(encoding, SRType_LSR);
2632}
2633
2634// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2635// shifting in zeros, and writes the result to the destination register. The variable number
2636// of bits is read from the bottom byte of a register. It can optionally update the condition
2637// flags based on the result.
2638bool
2639EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2640{
2641#if 0
2642 // ARM pseudo code...
2643 if ConditionPassed() then
2644 EncodingSpecificOperations();
2645 shift_n = UInt(R[m]<7:0>);
2646 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2647 R[d] = result;
2648 if setflags then
2649 APSR.N = result<31>;
2650 APSR.Z = IsZeroBit(result);
2651 APSR.C = carry;
2652 // APSR.V unchanged
2653#endif
2654
2655 return EmulateShiftReg(encoding, SRType_LSR);
2656}
2657
Johnny Cheneeab4852011-02-16 22:14:44 +00002658// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2659// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2660// It can optionally update the condition flags based on the result.
2661bool
2662EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2663{
2664#if 0
2665 // ARM pseudo code...
2666 if ConditionPassed() then
2667 EncodingSpecificOperations();
2668 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2669 if d == 15 then // Can only occur for ARM encoding
2670 ALUWritePC(result); // setflags is always FALSE here
2671 else
2672 R[d] = result;
2673 if setflags then
2674 APSR.N = result<31>;
2675 APSR.Z = IsZeroBit(result);
2676 APSR.C = carry;
2677 // APSR.V unchanged
2678#endif
2679
2680 return EmulateShiftImm(encoding, SRType_ROR);
2681}
2682
2683// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2684// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2685// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2686// flags based on the result.
2687bool
2688EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2689{
2690#if 0
2691 // ARM pseudo code...
2692 if ConditionPassed() then
2693 EncodingSpecificOperations();
2694 shift_n = UInt(R[m]<7:0>);
2695 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2696 R[d] = result;
2697 if setflags then
2698 APSR.N = result<31>;
2699 APSR.Z = IsZeroBit(result);
2700 APSR.C = carry;
2701 // APSR.V unchanged
2702#endif
2703
2704 return EmulateShiftReg(encoding, SRType_ROR);
2705}
2706
2707// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2708// with the carry flag shifted into bit [31].
2709//
2710// RRX can optionally update the condition flags based on the result.
2711// In that case, bit [0] is shifted into the carry flag.
2712bool
2713EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2714{
2715#if 0
2716 // ARM pseudo code...
2717 if ConditionPassed() then
2718 EncodingSpecificOperations();
2719 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2720 if d == 15 then // Can only occur for ARM encoding
2721 ALUWritePC(result); // setflags is always FALSE here
2722 else
2723 R[d] = result;
2724 if setflags then
2725 APSR.N = result<31>;
2726 APSR.Z = IsZeroBit(result);
2727 APSR.C = carry;
2728 // APSR.V unchanged
2729#endif
2730
2731 return EmulateShiftImm(encoding, SRType_RRX);
2732}
2733
Johnny Chen41a0a152011-02-16 01:27:54 +00002734bool
2735EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2736{
2737 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2738
Johnny Chen82f16aa2011-02-15 20:10:55 +00002739 bool success = false;
2740 const uint32_t opcode = OpcodeAsUnsigned (&success);
2741 if (!success)
2742 return false;
2743
2744 if (ConditionPassed())
2745 {
Johnny Chene7f89532011-02-15 23:22:46 +00002746 uint32_t Rd; // the destination register
2747 uint32_t Rm; // the first operand register
2748 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002749 uint32_t carry; // the carry bit after the shift operation
2750 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002751
2752 // Special case handling!
2753 // A8.6.139 ROR (immediate) -- Encoding T1
2754 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2755 {
2756 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2757 // have the same decoding of bit fields as the other Thumb2 shift operations.
2758 encoding = eEncodingT2;
2759 }
2760
Johnny Chen82f16aa2011-02-15 20:10:55 +00002761 switch (encoding) {
2762 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002763 // Due to the above special case handling!
2764 assert(shift_type != SRType_ROR);
2765
Johnny Chen82f16aa2011-02-15 20:10:55 +00002766 Rd = Bits32(opcode, 2, 0);
2767 Rm = Bits32(opcode, 5, 3);
2768 setflags = !InITBlock();
2769 imm5 = Bits32(opcode, 10, 6);
2770 break;
2771 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002772 // A8.6.141 RRX
2773 assert(shift_type != SRType_RRX);
2774
Johnny Chen82f16aa2011-02-15 20:10:55 +00002775 Rd = Bits32(opcode, 11, 8);
2776 Rm = Bits32(opcode, 3, 0);
2777 setflags = BitIsSet(opcode, 20);
2778 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2779 if (BadReg(Rd) || BadReg(Rm))
2780 return false;
2781 break;
2782 case eEncodingA1:
2783 Rd = Bits32(opcode, 15, 12);
2784 Rm = Bits32(opcode, 3, 0);
2785 setflags = BitIsSet(opcode, 20);
2786 imm5 = Bits32(opcode, 11, 7);
2787 break;
2788 default:
2789 return false;
2790 }
2791
Johnny Cheneeab4852011-02-16 22:14:44 +00002792 // A8.6.139 ROR (immediate)
2793 if (shift_type == SRType_ROR && imm5 == 0)
2794 shift_type = SRType_RRX;
2795
Johnny Chen82f16aa2011-02-15 20:10:55 +00002796 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002797 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002798 if (!success)
2799 return false;
2800
Johnny Cheneeab4852011-02-16 22:14:44 +00002801 // Decode the shift amount if not RRX.
2802 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002803
Johnny Chene97c0d52011-02-18 19:32:20 +00002804 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002805
2806 // The context specifies that an immediate is to be moved into Rd.
2807 EmulateInstruction::Context context;
2808 context.type = EmulateInstruction::eContextImmediate;
2809 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002810
Johnny Chen10530c22011-02-17 22:37:12 +00002811 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002812 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002813 }
2814 return true;
2815}
2816
Johnny Chene7f89532011-02-15 23:22:46 +00002817bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002818EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002819{
Johnny Chen41a0a152011-02-16 01:27:54 +00002820 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002821
2822 bool success = false;
2823 const uint32_t opcode = OpcodeAsUnsigned (&success);
2824 if (!success)
2825 return false;
2826
2827 if (ConditionPassed())
2828 {
2829 uint32_t Rd; // the destination register
2830 uint32_t Rn; // the first operand register
2831 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2832 uint32_t carry; // the carry bit after the shift operation
2833 bool setflags;
2834 switch (encoding) {
2835 case eEncodingT1:
2836 Rd = Bits32(opcode, 2, 0);
2837 Rn = Rd;
2838 Rm = Bits32(opcode, 5, 3);
2839 setflags = !InITBlock();
2840 break;
2841 case eEncodingT2:
2842 Rd = Bits32(opcode, 11, 8);
2843 Rn = Bits32(opcode, 19, 16);
2844 Rm = Bits32(opcode, 3, 0);
2845 setflags = BitIsSet(opcode, 20);
2846 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2847 return false;
2848 break;
2849 case eEncodingA1:
2850 Rd = Bits32(opcode, 15, 12);
2851 Rn = Bits32(opcode, 3, 0);
2852 Rm = Bits32(opcode, 11, 8);
2853 setflags = BitIsSet(opcode, 20);
2854 if (Rd == 15 || Rn == 15 || Rm == 15)
2855 return false;
2856 break;
2857 default:
2858 return false;
2859 }
2860
2861 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002862 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002863 if (!success)
2864 return false;
2865 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002866 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002867 if (!success)
2868 return false;
2869
2870 // Get the shift amount.
2871 uint32_t amt = Bits32(val, 7, 0);
2872
Johnny Chene97c0d52011-02-18 19:32:20 +00002873 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002874
2875 // The context specifies that an immediate is to be moved into Rd.
2876 EmulateInstruction::Context context;
2877 context.type = EmulateInstruction::eContextImmediate;
2878 context.SetNoArgs ();
2879
Johnny Chen10530c22011-02-17 22:37:12 +00002880 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002881 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002882 }
2883 return true;
2884}
2885
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002886// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002887// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002888// can be written back to the base register.
2889bool
2890EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2891{
2892#if 0
2893 // ARM pseudo code...
2894 if ConditionPassed()
2895 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2896 address = R[n];
2897
2898 for i = 0 to 14
2899 if registers<i> == '1' then
2900 R[i] = MemA[address, 4]; address = address + 4;
2901 if registers<15> == '1' then
2902 LoadWritePC (MemA[address, 4]);
2903
2904 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2905 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2906
2907#endif
2908
2909 bool success = false;
2910 const uint32_t opcode = OpcodeAsUnsigned (&success);
2911 if (!success)
2912 return false;
2913
2914 if (ConditionPassed())
2915 {
2916 uint32_t n;
2917 uint32_t registers = 0;
2918 bool wback;
2919 const uint32_t addr_byte_size = GetAddressByteSize();
2920 switch (encoding)
2921 {
2922 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002923 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002924 n = Bits32 (opcode, 10, 8);
2925 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002926 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002927 wback = BitIsClear (registers, n);
2928 // if BitCount(registers) < 1 then UNPREDICTABLE;
2929 if (BitCount(registers) < 1)
2930 return false;
2931 break;
2932 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002933 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2934 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002935 n = Bits32 (opcode, 19, 16);
2936 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002937 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002938 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002939
2940 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002941 if ((n == 15)
2942 || (BitCount (registers) < 2)
2943 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2944 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002945
2946 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002947 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002948 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002949
2950 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002951 if (wback
2952 && BitIsSet (registers, n))
2953 return false;
2954 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002955
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002956 case eEncodingA1:
2957 n = Bits32 (opcode, 19, 16);
2958 registers = Bits32 (opcode, 15, 0);
2959 wback = BitIsSet (opcode, 21);
2960 if ((n == 15)
2961 || (BitCount (registers) < 1))
2962 return false;
2963 break;
2964 default:
2965 return false;
2966 }
2967
2968 int32_t offset = 0;
2969 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2970 if (!success)
2971 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002972
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002973 EmulateInstruction::Context context;
2974 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2975 Register dwarf_reg;
2976 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2977 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002978
2979 for (int i = 0; i < 14; ++i)
2980 {
2981 if (BitIsSet (registers, i))
2982 {
Caroline Tice85aab332011-02-08 23:56:10 +00002983 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002984 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002985 if (wback && (n == 13)) // Pop Instruction
2986 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2987
2988 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002989 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002990 if (!success)
2991 return false;
2992
2993 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2994 return false;
2995
2996 offset += addr_byte_size;
2997 }
2998 }
2999
3000 if (BitIsSet (registers, 15))
3001 {
3002 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003003 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003004 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003005 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003006 if (!success)
3007 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003008 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003009 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003010 return false;
3011 }
3012
3013 if (wback && BitIsClear (registers, n))
3014 {
Caroline Ticefa172202011-02-11 22:49:54 +00003015 // R[n] = R[n] + 4 * BitCount (registers)
3016 int32_t offset = addr_byte_size * BitCount (registers);
3017 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003018 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003019
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3021 return false;
3022 }
3023 if (wback && BitIsSet (registers, n))
3024 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003025 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003026 }
3027 return true;
3028}
Caroline Tice713c2662011-02-11 17:59:55 +00003029
3030// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3031// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3032// can optionally be written back tot he base registers.
3033bool
3034EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3035{
3036#if 0
3037 // ARM pseudo code...
3038 if ConditionPassed() then
3039 EncodingSpecificOperations();
3040 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003041
Caroline Tice713c2662011-02-11 17:59:55 +00003042 for i = 0 to 14
3043 if registers<i> == ’1’ then
3044 R[i] = MemA[address,4]; address = address + 4;
3045
3046 if registers<15> == ’1’ then
3047 LoadWritePC(MemA[address,4]);
3048
3049 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3050 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3051#endif
3052
3053 bool success = false;
3054 const uint32_t opcode = OpcodeAsUnsigned (&success);
3055 if (!success)
3056 return false;
3057
3058 if (ConditionPassed())
3059 {
3060 uint32_t n;
3061 uint32_t registers = 0;
3062 bool wback;
3063 const uint32_t addr_byte_size = GetAddressByteSize();
3064
3065 // EncodingSpecificOperations();
3066 switch (encoding)
3067 {
3068 case eEncodingA1:
3069 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3070 n = Bits32 (opcode, 19, 16);
3071 registers = Bits32 (opcode, 15, 0);
3072 wback = BitIsSet (opcode, 21);
3073
3074 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3075 if ((n == 15) || (BitCount (registers) < 1))
3076 return false;
3077
3078 break;
3079
3080 default:
3081 return false;
3082 }
3083 // address = R[n] - 4*BitCount(registers) + 4;
3084
3085 int32_t offset = 0;
3086 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3087
3088 if (!success)
3089 return false;
3090
3091 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3092
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003093 EmulateInstruction::Context context;
3094 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3095 Register dwarf_reg;
3096 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3097 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003098
3099 // for i = 0 to 14
3100 for (int i = 0; i < 14; ++i)
3101 {
3102 // if registers<i> == ’1’ then
3103 if (BitIsSet (registers, i))
3104 {
3105 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003106 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003107 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003108 if (!success)
3109 return false;
3110 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3111 return false;
3112 offset += addr_byte_size;
3113 }
3114 }
3115
3116 // if registers<15> == ’1’ then
3117 // LoadWritePC(MemA[address,4]);
3118 if (BitIsSet (registers, 15))
3119 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003120 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003121 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003122 if (!success)
3123 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003124 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003125 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003126 return false;
3127 }
3128
3129 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3130 if (wback && BitIsClear (registers, n))
3131 {
Caroline Tice713c2662011-02-11 17:59:55 +00003132 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3133 if (!success)
3134 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003135
3136 offset = (addr_byte_size * BitCount (registers)) * -1;
3137 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003138 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003139 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003140 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3141 return false;
3142 }
3143
3144 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3145 if (wback && BitIsSet (registers, n))
3146 return WriteBits32Unknown (n);
3147 }
3148 return true;
3149}
3150
3151// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3152// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3153// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003154bool
3155EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3156{
3157#if 0
3158 // ARM pseudo code...
3159 if ConditionPassed() then
3160 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3161 address = R[n] - 4*BitCount(registers);
3162
3163 for i = 0 to 14
3164 if registers<i> == ’1’ then
3165 R[i] = MemA[address,4]; address = address + 4;
3166 if registers<15> == ’1’ then
3167 LoadWritePC(MemA[address,4]);
3168
3169 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3170 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3171#endif
3172
3173 bool success = false;
3174 const uint32_t opcode = OpcodeAsUnsigned (&success);
3175 if (!success)
3176 return false;
3177
3178 if (ConditionPassed())
3179 {
3180 uint32_t n;
3181 uint32_t registers = 0;
3182 bool wback;
3183 const uint32_t addr_byte_size = GetAddressByteSize();
3184 switch (encoding)
3185 {
3186 case eEncodingT1:
3187 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3188 n = Bits32 (opcode, 19, 16);
3189 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003190 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003191 wback = BitIsSet (opcode, 21);
3192
3193 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3194 if ((n == 15)
3195 || (BitCount (registers) < 2)
3196 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3197 return false;
3198
3199 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003200 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003201 return false;
3202
3203 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3204 if (wback && BitIsSet (registers, n))
3205 return false;
3206
3207 break;
3208
3209 case eEncodingA1:
3210 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3211 n = Bits32 (opcode, 19, 16);
3212 registers = Bits32 (opcode, 15, 0);
3213 wback = BitIsSet (opcode, 21);
3214
3215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3216 if ((n == 15) || (BitCount (registers) < 1))
3217 return false;
3218
3219 break;
3220
3221 default:
3222 return false;
3223 }
3224
Caroline Tice713c2662011-02-11 17:59:55 +00003225 // address = R[n] - 4*BitCount(registers);
3226
Caroline Tice0b29e242011-02-08 23:16:02 +00003227 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003228 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3229
3230 if (!success)
3231 return false;
3232
3233 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003234 EmulateInstruction::Context context;
3235 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3236 Register dwarf_reg;
3237 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3238 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003239
3240 for (int i = 0; i < 14; ++i)
3241 {
3242 if (BitIsSet (registers, i))
3243 {
3244 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003245 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003246 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003247 if (!success)
3248 return false;
3249
3250 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3251 return false;
3252
3253 offset += addr_byte_size;
3254 }
3255 }
3256
3257 // if registers<15> == ’1’ then
3258 // LoadWritePC(MemA[address,4]);
3259 if (BitIsSet (registers, 15))
3260 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003261 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003262 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003263 if (!success)
3264 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003265 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003266 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003267 return false;
3268 }
3269
3270 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3271 if (wback && BitIsClear (registers, n))
3272 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003273 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3274 if (!success)
3275 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003276
3277 offset = (addr_byte_size * BitCount (registers)) * -1;
3278 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003279 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003280 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003281 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3282 return false;
3283 }
3284
3285 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3286 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003287 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003288 }
3289 return true;
3290}
Caroline Tice85aab332011-02-08 23:56:10 +00003291
Caroline Tice713c2662011-02-11 17:59:55 +00003292// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3293// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3294// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003295bool
3296EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3297{
3298#if 0
3299 if ConditionPassed() then
3300 EncodingSpecificOperations();
3301 address = R[n] + 4;
3302
3303 for i = 0 to 14
3304 if registers<i> == ’1’ then
3305 R[i] = MemA[address,4]; address = address + 4;
3306 if registers<15> == ’1’ then
3307 LoadWritePC(MemA[address,4]);
3308
3309 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3310 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3311#endif
3312
3313 bool success = false;
3314 const uint32_t opcode = OpcodeAsUnsigned (&success);
3315 if (!success)
3316 return false;
3317
3318 if (ConditionPassed())
3319 {
3320 uint32_t n;
3321 uint32_t registers = 0;
3322 bool wback;
3323 const uint32_t addr_byte_size = GetAddressByteSize();
3324 switch (encoding)
3325 {
3326 case eEncodingA1:
3327 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3328 n = Bits32 (opcode, 19, 16);
3329 registers = Bits32 (opcode, 15, 0);
3330 wback = BitIsSet (opcode, 21);
3331
3332 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3333 if ((n == 15) || (BitCount (registers) < 1))
3334 return false;
3335
3336 break;
3337 default:
3338 return false;
3339 }
3340 // address = R[n] + 4;
3341
3342 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003343 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3344
3345 if (!success)
3346 return false;
3347
3348 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003349
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003350 EmulateInstruction::Context context;
3351 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3352 Register dwarf_reg;
3353 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3354 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003355
3356 for (int i = 0; i < 14; ++i)
3357 {
3358 if (BitIsSet (registers, i))
3359 {
3360 // R[i] = MemA[address,4]; address = address + 4;
3361
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003362 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003363 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003364 if (!success)
3365 return false;
3366
3367 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3368 return false;
3369
3370 offset += addr_byte_size;
3371 }
3372 }
3373
3374 // if registers<15> == ’1’ then
3375 // LoadWritePC(MemA[address,4]);
3376 if (BitIsSet (registers, 15))
3377 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003378 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003379 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003380 if (!success)
3381 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003382 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003383 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003384 return false;
3385 }
3386
3387 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3388 if (wback && BitIsClear (registers, n))
3389 {
Caroline Tice85aab332011-02-08 23:56:10 +00003390 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3391 if (!success)
3392 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003393
3394 offset = addr_byte_size * BitCount (registers);
3395 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003396 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003397 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003398 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3399 return false;
3400 }
3401
3402 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3403 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003404 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003405 }
3406 return true;
3407}
Caroline Tice0b29e242011-02-08 23:16:02 +00003408
Johnny Chenef21b592011-02-10 01:52:38 +00003409// Load Register (immediate) calculates an address from a base register value and
3410// an immediate offset, loads a word from memory, and writes to a register.
3411// LDR (immediate, Thumb)
3412bool
3413EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3414{
3415#if 0
3416 // ARM pseudo code...
3417 if (ConditionPassed())
3418 {
3419 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3420 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3421 address = if index then offset_addr else R[n];
3422 data = MemU[address,4];
3423 if wback then R[n] = offset_addr;
3424 if t == 15 then
3425 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3426 elsif UnalignedSupport() || address<1:0> = '00' then
3427 R[t] = data;
3428 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3429 }
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 Rt; // the destination register
3440 uint32_t Rn; // the base register
3441 uint32_t imm32; // the immediate offset used to form the address
3442 addr_t offset_addr; // the offset address
3443 addr_t address; // the calculated address
3444 uint32_t data; // the literal data value from memory load
3445 bool add, index, wback;
3446 switch (encoding) {
3447 case eEncodingT1:
3448 Rt = Bits32(opcode, 5, 3);
3449 Rn = Bits32(opcode, 2, 0);
3450 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3451 // index = TRUE; add = TRUE; wback = FALSE
3452 add = true;
3453 index = true;
3454 wback = false;
3455 break;
3456 default:
3457 return false;
3458 }
3459 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3460 if (!success)
3461 return false;
3462 if (add)
3463 offset_addr = base + imm32;
3464 else
3465 offset_addr = base - imm32;
3466
3467 address = (index ? offset_addr : base);
3468
3469 if (wback)
3470 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003471 EmulateInstruction::Context ctx;
3472 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3473 Register dwarf_reg;
3474 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3475 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3476
Johnny Chenef21b592011-02-10 01:52:38 +00003477 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3478 return false;
3479 }
3480
3481 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003482 EmulateInstruction::Context context;
3483 context.type = EmulateInstruction::eContextImmediate;
3484 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003485
3486 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003487 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003488 if (!success)
3489 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003490
3491 if (Rt == 15)
3492 {
3493 if (Bits32(address, 1, 0) == 0)
3494 {
Johnny Chen668b4512011-02-15 21:08:58 +00003495 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003496 return false;
3497 }
3498 else
3499 return false;
3500 }
3501 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3502 {
3503 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3504 return false;
3505 }
3506 else
3507 return false;
3508 }
3509 return true;
3510}
3511
Caroline Ticeaf556562011-02-15 18:42:15 +00003512// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3513// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3514// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003515bool
3516EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3517{
3518#if 0
3519 if ConditionPassed() then
3520 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3521 address = R[n];
3522
3523 for i = 0 to 14
3524 if registers<i> == ’1’ then
3525 if i == n && wback && i != LowestSetBit(registers) then
3526 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3527 else
3528 MemA[address,4] = R[i];
3529 address = address + 4;
3530
3531 if registers<15> == ’1’ then // Only possible for encoding A1
3532 MemA[address,4] = PCStoreValue();
3533 if wback then R[n] = R[n] + 4*BitCount(registers);
3534#endif
3535
3536 bool success = false;
3537 const uint32_t opcode = OpcodeAsUnsigned (&success);
3538 if (!success)
3539 return false;
3540
3541 if (ConditionPassed ())
3542 {
3543 uint32_t n;
3544 uint32_t registers = 0;
3545 bool wback;
3546 const uint32_t addr_byte_size = GetAddressByteSize();
3547
3548 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3549 switch (encoding)
3550 {
3551 case eEncodingT1:
3552 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3553 n = Bits32 (opcode, 10, 8);
3554 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003555 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003556 wback = true;
3557
3558 // if BitCount(registers) < 1 then UNPREDICTABLE;
3559 if (BitCount (registers) < 1)
3560 return false;
3561
3562 break;
3563
3564 case eEncodingT2:
3565 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3566 n = Bits32 (opcode, 19, 16);
3567 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003568 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003569 wback = BitIsSet (opcode, 21);
3570
3571 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3572 if ((n == 15) || (BitCount (registers) < 2))
3573 return false;
3574
3575 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3576 if (wback && BitIsSet (registers, n))
3577 return false;
3578
3579 break;
3580
3581 case eEncodingA1:
3582 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3583 n = Bits32 (opcode, 19, 16);
3584 registers = Bits32 (opcode, 15, 0);
3585 wback = BitIsSet (opcode, 21);
3586
3587 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3588 if ((n == 15) || (BitCount (registers) < 1))
3589 return false;
3590
3591 break;
3592
3593 default:
3594 return false;
3595 }
3596
3597 // address = R[n];
3598 int32_t offset = 0;
3599 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3600 if (!success)
3601 return false;
3602
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003603 EmulateInstruction::Context context;
3604 context.type = EmulateInstruction::eContextRegisterStore;
3605 Register base_reg;
3606 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003607
3608 // for i = 0 to 14
3609 for (int i = 0; i < 14; ++i)
3610 {
3611 int lowest_set_bit = 14;
3612 // if registers<i> == ’1’ then
3613 if (BitIsSet (registers, i))
3614 {
3615 if (i < lowest_set_bit)
3616 lowest_set_bit = i;
3617 // if i == n && wback && i != LowestSetBit(registers) then
3618 if ((i == n) && wback && (i != lowest_set_bit))
3619 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3620 WriteBits32UnknownToMemory (address + offset);
3621 else
3622 {
3623 // MemA[address,4] = R[i];
3624 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3625 if (!success)
3626 return false;
3627
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003628 Register data_reg;
3629 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3630 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003631 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003632 return false;
3633 }
3634
3635 // address = address + 4;
3636 offset += addr_byte_size;
3637 }
3638 }
3639
3640 // if registers<15> == ’1’ then // Only possible for encoding A1
3641 // MemA[address,4] = PCStoreValue();
3642 if (BitIsSet (registers, 15))
3643 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003644 Register pc_reg;
3645 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3646 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003647 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3648 if (!success)
3649 return false;
3650
Caroline Ticecc96eb52011-02-17 19:20:40 +00003651 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003652 return false;
3653 }
3654
3655 // if wback then R[n] = R[n] + 4*BitCount(registers);
3656 if (wback)
3657 {
3658 offset = addr_byte_size * BitCount (registers);
3659 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003660 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003661 addr_t data = address + offset;
3662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3663 return false;
3664 }
3665 }
3666 return true;
3667}
3668
Caroline Ticeaf556562011-02-15 18:42:15 +00003669// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3670// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3671// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003672bool
3673EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3674{
3675#if 0
3676 if ConditionPassed() then
3677 EncodingSpecificOperations();
3678 address = R[n] - 4*BitCount(registers) + 4;
3679
3680 for i = 0 to 14
3681 if registers<i> == ’1’ then
3682 if i == n && wback && i != LowestSetBit(registers) then
3683 MemA[address,4] = bits(32) UNKNOWN;
3684 else
3685 MemA[address,4] = R[i];
3686 address = address + 4;
3687
3688 if registers<15> == ’1’ then
3689 MemA[address,4] = PCStoreValue();
3690
3691 if wback then R[n] = R[n] - 4*BitCount(registers);
3692#endif
3693
3694 bool success = false;
3695 const uint32_t opcode = OpcodeAsUnsigned (&success);
3696 if (!success)
3697 return false;
3698
3699 if (ConditionPassed ())
3700 {
3701 uint32_t n;
3702 uint32_t registers = 0;
3703 bool wback;
3704 const uint32_t addr_byte_size = GetAddressByteSize();
3705
3706 // EncodingSpecificOperations();
3707 switch (encoding)
3708 {
3709 case eEncodingA1:
3710 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3711 n = Bits32 (opcode, 19, 16);
3712 registers = Bits32 (opcode, 15, 0);
3713 wback = BitIsSet (opcode, 21);
3714
3715 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3716 if ((n == 15) || (BitCount (registers) < 1))
3717 return false;
3718 break;
3719 default:
3720 return false;
3721 }
3722
3723 // address = R[n] - 4*BitCount(registers) + 4;
3724 int32_t offset = 0;
3725 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3726 if (!success)
3727 return false;
3728
3729 address = address - (addr_byte_size * BitCount (registers)) + 4;
3730
3731 EmulateInstruction::Context context;
3732 context.type = EmulateInstruction::eContextRegisterStore;
3733 Register base_reg;
3734 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3735
3736 // for i = 0 to 14
3737 for (int i = 0; i < 14; ++i)
3738 {
3739 int lowest_bit_set = 14;
3740 // if registers<i> == ’1’ then
3741 if (BitIsSet (registers, i))
3742 {
3743 if (i < lowest_bit_set)
3744 lowest_bit_set = i;
3745 //if i == n && wback && i != LowestSetBit(registers) then
3746 if ((i == n) && wback && (i != lowest_bit_set))
3747 // MemA[address,4] = bits(32) UNKNOWN;
3748 WriteBits32UnknownToMemory (address + offset);
3749 else
3750 {
3751 // MemA[address,4] = R[i];
3752 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3753 if (!success)
3754 return false;
3755
3756 Register data_reg;
3757 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3758 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003759 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003760 return false;
3761 }
3762
3763 // address = address + 4;
3764 offset += addr_byte_size;
3765 }
3766 }
3767
3768 // if registers<15> == ’1’ then
3769 // MemA[address,4] = PCStoreValue();
3770 if (BitIsSet (registers, 15))
3771 {
3772 Register pc_reg;
3773 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3774 context.SetRegisterPlusOffset (pc_reg, 8);
3775 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3776 if (!success)
3777 return false;
3778
Caroline Ticecc96eb52011-02-17 19:20:40 +00003779 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003780 return false;
3781 }
3782
3783 // if wback then R[n] = R[n] - 4*BitCount(registers);
3784 if (wback)
3785 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003786 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003787 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3788 context.SetImmediateSigned (offset);
3789 addr_t data = address + offset;
3790 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3791 return false;
3792 }
3793 }
3794 return true;
3795}
3796
Caroline Ticeaf556562011-02-15 18:42:15 +00003797// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3798// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3799// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003800bool
3801EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3802{
3803#if 0
3804 if ConditionPassed() then
3805 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3806 address = R[n] - 4*BitCount(registers);
3807
3808 for i = 0 to 14
3809 if registers<i> == ’1’ then
3810 if i == n && wback && i != LowestSetBit(registers) then
3811 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3812 else
3813 MemA[address,4] = R[i];
3814 address = address + 4;
3815
3816 if registers<15> == ’1’ then // Only possible for encoding A1
3817 MemA[address,4] = PCStoreValue();
3818
3819 if wback then R[n] = R[n] - 4*BitCount(registers);
3820#endif
3821
3822
3823 bool success = false;
3824 const uint32_t opcode = OpcodeAsUnsigned (&success);
3825 if (!success)
3826 return false;
3827
3828 if (ConditionPassed ())
3829 {
3830 uint32_t n;
3831 uint32_t registers = 0;
3832 bool wback;
3833 const uint32_t addr_byte_size = GetAddressByteSize();
3834
3835 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3836 switch (encoding)
3837 {
3838 case eEncodingT1:
3839 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3840 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3841 {
3842 // See PUSH
3843 }
3844 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3845 n = Bits32 (opcode, 19, 16);
3846 registers = Bits32 (opcode, 15, 0);
3847 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3848 wback = BitIsSet (opcode, 21);
3849 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3850 if ((n == 15) || BitCount (registers) < 2)
3851 return false;
3852 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3853 if (wback && BitIsSet (registers, n))
3854 return false;
3855 break;
3856
3857 case eEncodingA1:
3858 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3859 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3860 {
3861 // See Push
3862 }
3863 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3864 n = Bits32 (opcode, 19, 16);
3865 registers = Bits32 (opcode, 15, 0);
3866 wback = BitIsSet (opcode, 21);
3867 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3868 if ((n == 15) || BitCount (registers) < 1)
3869 return false;
3870 break;
3871
3872 default:
3873 return false;
3874 }
3875
3876 // address = R[n] - 4*BitCount(registers);
3877
3878 int32_t offset = 0;
3879 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3880 if (!success)
3881 return false;
3882
3883 address = address - (addr_byte_size * BitCount (registers));
3884
3885 EmulateInstruction::Context context;
3886 context.type = EmulateInstruction::eContextRegisterStore;
3887 Register base_reg;
3888 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3889
3890 // for i = 0 to 14
3891 for (int i = 0; i < 14; ++i)
3892 {
3893 uint32_t lowest_set_bit = 14;
3894 // if registers<i> == ’1’ then
3895 if (BitIsSet (registers, i))
3896 {
3897 if (i < lowest_set_bit)
3898 lowest_set_bit = i;
3899 // if i == n && wback && i != LowestSetBit(registers) then
3900 if ((i == n) && wback && (i != lowest_set_bit))
3901 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3902 WriteBits32UnknownToMemory (address + offset);
3903 else
3904 {
3905 // MemA[address,4] = R[i];
3906 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3907 if (!success)
3908 return false;
3909
3910 Register data_reg;
3911 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3912 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003913 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003914 return false;
3915 }
3916
3917 // address = address + 4;
3918 offset += addr_byte_size;
3919 }
3920 }
3921
3922 // if registers<15> == ’1’ then // Only possible for encoding A1
3923 // MemA[address,4] = PCStoreValue();
3924 if (BitIsSet (registers, 15))
3925 {
3926 Register pc_reg;
3927 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3928 context.SetRegisterPlusOffset (pc_reg, 8);
3929 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3930 if (!success)
3931 return false;
3932
Caroline Ticecc96eb52011-02-17 19:20:40 +00003933 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003934 return false;
3935 }
3936
3937 // if wback then R[n] = R[n] - 4*BitCount(registers);
3938 if (wback)
3939 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003940 offset = (addr_byte_size * BitCount (registers)) * -1;
3941 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3942 context.SetImmediateSigned (offset);
3943 addr_t data = address + offset;
3944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3945 return false;
3946 }
3947 }
3948 return true;
3949}
3950
3951// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3952// from a base register. The consecutive memory locations start just above this address, and the address of the last
3953// of those locations can optionally be written back to the base register.
3954bool
3955EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3956{
3957#if 0
3958 if ConditionPassed() then
3959 EncodingSpecificOperations();
3960 address = R[n] + 4;
3961
3962 for i = 0 to 14
3963 if registers<i> == ’1’ then
3964 if i == n && wback && i != LowestSetBit(registers) then
3965 MemA[address,4] = bits(32) UNKNOWN;
3966 else
3967 MemA[address,4] = R[i];
3968 address = address + 4;
3969
3970 if registers<15> == ’1’ then
3971 MemA[address,4] = PCStoreValue();
3972
3973 if wback then R[n] = R[n] + 4*BitCount(registers);
3974#endif
3975
3976 bool success = false;
3977 const uint32_t opcode = OpcodeAsUnsigned (&success);
3978 if (!success)
3979 return false;
3980
3981 if (ConditionPassed())
3982 {
3983 uint32_t n;
3984 uint32_t registers = 0;
3985 bool wback;
3986 const uint32_t addr_byte_size = GetAddressByteSize();
3987
3988 // EncodingSpecificOperations();
3989 switch (encoding)
3990 {
3991 case eEncodingA1:
3992 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3993 n = Bits32 (opcode, 19, 16);
3994 registers = Bits32 (opcode, 15, 0);
3995 wback = BitIsSet (opcode, 21);
3996
3997 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3998 if ((n == 15) && (BitCount (registers) < 1))
3999 return false;
4000 break;
4001 default:
4002 return false;
4003 }
4004 // address = R[n] + 4;
4005
4006 int32_t offset = 0;
4007 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4008 if (!success)
4009 return false;
4010
4011 address = address + addr_byte_size;
4012
4013 EmulateInstruction::Context context;
4014 context.type = EmulateInstruction::eContextRegisterStore;
4015 Register base_reg;
4016 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4017
4018 uint32_t lowest_set_bit = 14;
4019 // for i = 0 to 14
4020 for (int i = 0; i < 14; ++i)
4021 {
4022 // if registers<i> == ’1’ then
4023 if (BitIsSet (registers, i))
4024 {
4025 if (i < lowest_set_bit)
4026 lowest_set_bit = i;
4027 // if i == n && wback && i != LowestSetBit(registers) then
4028 if ((i == n) && wback && (i != lowest_set_bit))
4029 // MemA[address,4] = bits(32) UNKNOWN;
4030 WriteBits32UnknownToMemory (address + offset);
4031 // else
4032 else
4033 {
4034 // MemA[address,4] = R[i];
4035 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4036 if (!success)
4037 return false;
4038
4039 Register data_reg;
4040 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4041 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004042 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004043 return false;
4044 }
4045
4046 // address = address + 4;
4047 offset += addr_byte_size;
4048 }
4049 }
4050
4051 // if registers<15> == ’1’ then
4052 // MemA[address,4] = PCStoreValue();
4053 if (BitIsSet (registers, 15))
4054 {
4055 Register pc_reg;
4056 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4057 context.SetRegisterPlusOffset (pc_reg, 8);
4058 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4059 if (!success)
4060 return false;
4061
Caroline Ticecc96eb52011-02-17 19:20:40 +00004062 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004063 return false;
4064 }
4065
4066 // if wback then R[n] = R[n] + 4*BitCount(registers);
4067 if (wback)
4068 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004069 offset = addr_byte_size * BitCount (registers);
4070 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4071 context.SetImmediateSigned (offset);
4072 addr_t data = address + offset;
4073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4074 return false;
4075 }
4076 }
4077 return true;
4078}
Caroline Tice7fac8572011-02-15 22:53:54 +00004079
4080// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4081// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4082bool
4083EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4084{
4085#if 0
4086 if ConditionPassed() then
4087 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4088 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4089 address = if index then offset_addr else R[n];
4090 if UnalignedSupport() || address<1:0> == ’00’ then
4091 MemU[address,4] = R[t];
4092 else // Can only occur before ARMv7
4093 MemU[address,4] = bits(32) UNKNOWN;
4094 if wback then R[n] = offset_addr;
4095#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004096
Caroline Tice7fac8572011-02-15 22:53:54 +00004097 bool success = false;
4098 const uint32_t opcode = OpcodeAsUnsigned (&success);
4099 if (!success)
4100 return false;
4101
4102 if (ConditionPassed())
4103 {
4104 const uint32_t addr_byte_size = GetAddressByteSize();
4105
4106 uint32_t t;
4107 uint32_t n;
4108 uint32_t imm32;
4109 bool index;
4110 bool add;
4111 bool wback;
4112 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4113 switch (encoding)
4114 {
4115 case eEncodingT1:
4116 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4117 t = Bits32 (opcode, 2, 0);
4118 n = Bits32 (opcode, 5, 3);
4119 imm32 = Bits32 (opcode, 10, 6) << 2;
4120
4121 // index = TRUE; add = TRUE; wback = FALSE;
4122 index = true;
4123 add = false;
4124 wback = false;
4125 break;
4126
4127 case eEncodingT2:
4128 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4129 t = Bits32 (opcode, 10, 8);
4130 n = 13;
4131 imm32 = Bits32 (opcode, 7, 0) << 2;
4132
4133 // index = TRUE; add = TRUE; wback = FALSE;
4134 index = true;
4135 add = true;
4136 wback = false;
4137 break;
4138
4139 case eEncodingT3:
4140 // if Rn == ’1111’ then UNDEFINED;
4141 if (Bits32 (opcode, 19, 16) == 15)
4142 return false;
4143
4144 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4145 t = Bits32 (opcode, 15, 12);
4146 n = Bits32 (opcode, 19, 16);
4147 imm32 = Bits32 (opcode, 11, 0);
4148
4149 // index = TRUE; add = TRUE; wback = FALSE;
4150 index = true;
4151 add = true;
4152 wback = false;
4153
4154 // if t == 15 then UNPREDICTABLE;
4155 if (t == 15)
4156 return false;
4157 break;
4158
4159 case eEncodingT4:
4160 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4161 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4162 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4163 if ((Bits32 (opcode, 19, 16) == 15)
4164 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4165 return false;
4166
4167 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4168 t = Bits32 (opcode, 15, 12);
4169 n = Bits32 (opcode, 19, 16);
4170 imm32 = Bits32 (opcode, 7, 0);
4171
4172 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4173 index = BitIsSet (opcode, 10);
4174 add = BitIsSet (opcode, 9);
4175 wback = BitIsSet (opcode, 8);
4176
4177 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4178 if ((t == 15) || (wback && (n == t)))
4179 return false;
4180 break;
4181
4182 default:
4183 return false;
4184 }
4185
4186 addr_t offset_addr;
4187 addr_t address;
4188
4189 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4190 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4191 if (!success)
4192 return false;
4193
4194 if (add)
4195 offset_addr = base_address + imm32;
4196 else
4197 offset_addr = base_address - imm32;
4198
4199 // address = if index then offset_addr else R[n];
4200 if (index)
4201 address = offset_addr;
4202 else
4203 address = base_address;
4204
4205 EmulateInstruction::Context context;
4206 context.type = eContextRegisterStore;
4207 Register base_reg;
4208 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4209
4210 // if UnalignedSupport() || address<1:0> == ’00’ then
4211 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4212 {
4213 // MemU[address,4] = R[t];
4214 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4215 if (!success)
4216 return false;
4217
4218 Register data_reg;
4219 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4220 int32_t offset = address - base_address;
4221 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004222 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004223 return false;
4224 }
4225 else
4226 {
4227 // MemU[address,4] = bits(32) UNKNOWN;
4228 WriteBits32UnknownToMemory (address);
4229 }
4230
4231 // if wback then R[n] = offset_addr;
4232 if (wback)
4233 {
4234 context.type = eContextRegisterLoad;
4235 context.SetAddress (offset_addr);
4236 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4237 return false;
4238 }
4239 }
4240 return true;
4241}
Caroline Ticeaf556562011-02-15 18:42:15 +00004242
Caroline Tice3fd63e92011-02-16 00:33:43 +00004243// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4244// word from a register to memory. The offset register value can optionally be shifted.
4245bool
4246EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4247{
4248#if 0
4249 if ConditionPassed() then
4250 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4251 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4252 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4253 address = if index then offset_addr else R[n];
4254 if t == 15 then // Only possible for encoding A1
4255 data = PCStoreValue();
4256 else
4257 data = R[t];
4258 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4259 MemU[address,4] = data;
4260 else // Can only occur before ARMv7
4261 MemU[address,4] = bits(32) UNKNOWN;
4262 if wback then R[n] = offset_addr;
4263#endif
4264
4265 bool success = false;
4266 const uint32_t opcode = OpcodeAsUnsigned (&success);
4267 if (!success)
4268 return false;
4269
4270 if (ConditionPassed())
4271 {
4272 const uint32_t addr_byte_size = GetAddressByteSize();
4273
4274 uint32_t t;
4275 uint32_t n;
4276 uint32_t m;
4277 ARM_ShifterType shift_t;
4278 uint32_t shift_n;
4279 bool index;
4280 bool add;
4281 bool wback;
4282
4283 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4284 switch (encoding)
4285 {
4286 case eEncodingT1:
4287 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4288 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4289 t = Bits32 (opcode, 2, 0);
4290 n = Bits32 (opcode, 5, 3);
4291 m = Bits32 (opcode, 8, 6);
4292
4293 // index = TRUE; add = TRUE; wback = FALSE;
4294 index = true;
4295 add = true;
4296 wback = false;
4297
4298 // (shift_t, shift_n) = (SRType_LSL, 0);
4299 shift_t = SRType_LSL;
4300 shift_n = 0;
4301 break;
4302
4303 case eEncodingT2:
4304 // if Rn == ’1111’ then UNDEFINED;
4305 if (Bits32 (opcode, 19, 16) == 15)
4306 return false;
4307
4308 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4309 t = Bits32 (opcode, 15, 12);
4310 n = Bits32 (opcode, 19, 16);
4311 m = Bits32 (opcode, 3, 0);
4312
4313 // index = TRUE; add = TRUE; wback = FALSE;
4314 index = true;
4315 add = true;
4316 wback = false;
4317
4318 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4319 shift_t = SRType_LSL;
4320 shift_n = Bits32 (opcode, 5, 4);
4321
4322 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4323 if ((t == 15) || (BadReg (m)))
4324 return false;
4325 break;
4326
4327 case eEncodingA1:
4328 {
4329 // if P == ’0’ && W == ’1’ then SEE STRT;
4330 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4331 t = Bits32 (opcode, 15, 12);
4332 n = Bits32 (opcode, 19, 16);
4333 m = Bits32 (opcode, 3, 0);
4334
4335 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4336 index = BitIsSet (opcode, 24);
4337 add = BitIsSet (opcode, 23);
4338 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4339
4340 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4341 uint32_t typ = Bits32 (opcode, 6, 5);
4342 uint32_t imm5 = Bits32 (opcode, 11, 7);
4343 shift_n = DecodeImmShift(typ, imm5, shift_t);
4344
4345 // if m == 15 then UNPREDICTABLE;
4346 if (m == 15)
4347 return false;
4348
4349 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4350 if (wback && ((n == 15) || (n == t)))
4351 return false;
4352
4353 break;
4354 }
4355 default:
4356 return false;
4357 }
4358
4359 addr_t offset_addr;
4360 addr_t address;
4361 int32_t offset = 0;
4362
4363 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4364 if (!success)
4365 return false;
4366
4367 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4368 if (!success)
4369 return false;
4370
4371 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004372 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004373
4374 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4375 if (add)
4376 offset_addr = base_address + offset;
4377 else
4378 offset_addr = base_address - offset;
4379
4380 // address = if index then offset_addr else R[n];
4381 if (index)
4382 address = offset_addr;
4383 else
4384 address = base_address;
4385
4386 uint32_t data;
4387 // if t == 15 then // Only possible for encoding A1
4388 if (t == 15)
4389 // data = PCStoreValue();
4390 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4391 else
4392 // data = R[t];
4393 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4394
4395 if (!success)
4396 return false;
4397
4398 EmulateInstruction::Context context;
4399 context.type = eContextRegisterStore;
4400
4401 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4402 if (UnalignedSupport ()
4403 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4404 || CurrentInstrSet() == eModeARM)
4405 {
4406 // MemU[address,4] = data;
4407
4408 Register base_reg;
4409 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4410
4411 Register data_reg;
4412 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4413
4414 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004415 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004416 return false;
4417
4418 }
4419 else
4420 // MemU[address,4] = bits(32) UNKNOWN;
4421 WriteBits32UnknownToMemory (address);
4422
4423 // if wback then R[n] = offset_addr;
4424 if (wback)
4425 {
4426 context.type = eContextRegisterLoad;
4427 context.SetAddress (offset_addr);
4428 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4429 return false;
4430 }
4431
4432 }
4433 return true;
4434}
Caroline Tice73a29de2011-02-16 20:22:22 +00004435
4436bool
4437EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4438{
4439#if 0
4440 if ConditionPassed() then
4441 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4442 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4443 address = if index then offset_addr else R[n];
4444 MemU[address,1] = R[t]<7:0>;
4445 if wback then R[n] = offset_addr;
4446#endif
4447
4448
4449 bool success = false;
4450 const uint32_t opcode = OpcodeAsUnsigned (&success);
4451 if (!success)
4452 return false;
4453
4454 if (ConditionPassed ())
4455 {
4456 uint32_t t;
4457 uint32_t n;
4458 uint32_t imm32;
4459 bool index;
4460 bool add;
4461 bool wback;
4462 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4463 switch (encoding)
4464 {
4465 case eEncodingT1:
4466 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4467 t = Bits32 (opcode, 2, 0);
4468 n = Bits32 (opcode, 5, 3);
4469 imm32 = Bits32 (opcode, 10, 6);
4470
4471 // index = TRUE; add = TRUE; wback = FALSE;
4472 index = true;
4473 add = true;
4474 wback = false;
4475 break;
4476
4477 case eEncodingT2:
4478 // if Rn == ’1111’ then UNDEFINED;
4479 if (Bits32 (opcode, 19, 16) == 15)
4480 return false;
4481
4482 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4483 t = Bits32 (opcode, 15, 12);
4484 n = Bits32 (opcode, 19, 16);
4485 imm32 = Bits32 (opcode, 11, 0);
4486
4487 // index = TRUE; add = TRUE; wback = FALSE;
4488 index = true;
4489 add = true;
4490 wback = false;
4491
4492 // if BadReg(t) then UNPREDICTABLE;
4493 if (BadReg (t))
4494 return false;
4495 break;
4496
4497 case eEncodingT3:
4498 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4499 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4500 if (Bits32 (opcode, 19, 16) == 15)
4501 return false;
4502
4503 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4504 t = Bits32 (opcode, 15, 12);
4505 n = Bits32 (opcode, 19, 16);
4506 imm32 = Bits32 (opcode, 7, 0);
4507
4508 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4509 index = BitIsSet (opcode, 10);
4510 add = BitIsSet (opcode, 9);
4511 wback = BitIsSet (opcode, 8);
4512
4513 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4514 if ((BadReg (t)) || (wback && (n == t)))
4515 return false;
4516 break;
4517
4518 default:
4519 return false;
4520 }
4521
4522 addr_t offset_addr;
4523 addr_t address;
4524 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4525 if (!success)
4526 return false;
4527
4528 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4529 if (add)
4530 offset_addr = base_address + imm32;
4531 else
4532 offset_addr = base_address - imm32;
4533
4534 // address = if index then offset_addr else R[n];
4535 if (index)
4536 address = offset_addr;
4537 else
4538 address = base_address;
4539
Caroline Ticecc96eb52011-02-17 19:20:40 +00004540 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004541 Register base_reg;
4542 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4543
4544 Register data_reg;
4545 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4546
4547 EmulateInstruction::Context context;
4548 context.type = eContextRegisterStore;
4549 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4550
4551 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4552 if (!success)
4553 return false;
4554
4555 data = Bits32 (data, 7, 0);
4556
Caroline Ticecc96eb52011-02-17 19:20:40 +00004557 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004558 return false;
4559
4560 // if wback then R[n] = offset_addr;
4561 if (wback)
4562 {
4563 context.type = eContextRegisterLoad;
4564 context.SetAddress (offset_addr);
4565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4566 return false;
4567 }
4568
4569 }
4570
4571 return true;
4572}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004573
Johnny Chen157b9592011-02-18 21:13:05 +00004574// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4575// and writes the result to the destination register. It can optionally update the condition flags
4576// based on the result.
4577bool
4578EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4579{
4580#if 0
4581 // ARM pseudo code...
4582 if ConditionPassed() then
4583 EncodingSpecificOperations();
4584 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4585 if d == 15 then // Can only occur for ARM encoding
4586 ALUWritePC(result); // setflags is always FALSE here
4587 else
4588 R[d] = result;
4589 if setflags then
4590 APSR.N = result<31>;
4591 APSR.Z = IsZeroBit(result);
4592 APSR.C = carry;
4593 APSR.V = overflow;
4594#endif
4595
4596 bool success = false;
4597 const uint32_t opcode = OpcodeAsUnsigned (&success);
4598 if (!success)
4599 return false;
4600
4601 if (ConditionPassed())
4602 {
4603 uint32_t Rd, Rn;
4604 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4605 bool setflags;
4606 switch (encoding)
4607 {
4608 case eEncodingT1:
4609 Rd = Bits32(opcode, 11, 8);
4610 Rn = Bits32(opcode, 19, 16);
4611 setflags = BitIsSet(opcode, 20);
4612 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4613 if (BadReg(Rd) || BadReg(Rn))
4614 return false;
4615 break;
4616 case eEncodingA1:
4617 Rd = Bits32(opcode, 15, 12);
4618 Rn = Bits32(opcode, 19, 16);
4619 setflags = BitIsSet(opcode, 20);
4620 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4621 // TODO: Emulate SUBS PC, LR and related instructions.
4622 if (Rd == 15 && setflags)
4623 return false;
4624 break;
4625 default:
4626 return false;
4627 }
4628
4629 // Read the first operand.
4630 int32_t val1 = ReadCoreReg(Rn, &success);
4631 if (!success)
4632 return false;
4633
4634 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4635
4636 EmulateInstruction::Context context;
4637 context.type = EmulateInstruction::eContextImmediate;
4638 context.SetNoArgs ();
4639
4640 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4641 return false;
4642 }
4643 return true;
4644}
4645
4646// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4647// register value, and writes the result to the destination register. It can optionally update the
4648// condition flags based on the result.
4649bool
4650EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4651{
4652#if 0
4653 // ARM pseudo code...
4654 if ConditionPassed() then
4655 EncodingSpecificOperations();
4656 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4657 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4658 if d == 15 then // Can only occur for ARM encoding
4659 ALUWritePC(result); // setflags is always FALSE here
4660 else
4661 R[d] = result;
4662 if setflags then
4663 APSR.N = result<31>;
4664 APSR.Z = IsZeroBit(result);
4665 APSR.C = carry;
4666 APSR.V = overflow;
4667#endif
4668
4669 bool success = false;
4670 const uint32_t opcode = OpcodeAsUnsigned (&success);
4671 if (!success)
4672 return false;
4673
4674 if (ConditionPassed())
4675 {
4676 uint32_t Rd, Rn, Rm;
4677 ARM_ShifterType shift_t;
4678 uint32_t shift_n; // the shift applied to the value read from Rm
4679 bool setflags;
4680 switch (encoding)
4681 {
4682 case eEncodingT1:
4683 Rd = Rn = Bits32(opcode, 2, 0);
4684 Rm = Bits32(opcode, 5, 3);
4685 setflags = !InITBlock();
4686 shift_t = SRType_LSL;
4687 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004688 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004689 case eEncodingT2:
4690 Rd = Bits32(opcode, 11, 8);
4691 Rn = Bits32(opcode, 19, 16);
4692 Rm = Bits32(opcode, 3, 0);
4693 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004694 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004695 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4696 return false;
4697 break;
4698 case eEncodingA1:
4699 Rd = Bits32(opcode, 15, 12);
4700 Rn = Bits32(opcode, 19, 16);
4701 Rm = Bits32(opcode, 3, 0);
4702 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004703 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004704 // TODO: Emulate SUBS PC, LR and related instructions.
4705 if (Rd == 15 && setflags)
4706 return false;
4707 break;
4708 default:
4709 return false;
4710 }
4711
4712 // Read the first operand.
4713 int32_t val1 = ReadCoreReg(Rn, &success);
4714 if (!success)
4715 return false;
4716
4717 // Read the second operand.
4718 int32_t val2 = ReadCoreReg(Rm, &success);
4719 if (!success)
4720 return false;
4721
4722 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4723 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4724
4725 EmulateInstruction::Context context;
4726 context.type = EmulateInstruction::eContextImmediate;
4727 context.SetNoArgs ();
4728
4729 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4730 return false;
4731 }
4732 return true;
4733}
4734
Johnny Chena695f952011-02-23 21:24:25 +00004735// This instruction adds an immediate value to the PC value to form a PC-relative address,
4736// and writes the result to the destination register.
4737bool
4738EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4739{
4740#if 0
4741 // ARM pseudo code...
4742 if ConditionPassed() then
4743 EncodingSpecificOperations();
4744 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
4745 if d == 15 then // Can only occur for ARM encodings
4746 ALUWritePC(result);
4747 else
4748 R[d] = result;
4749#endif
4750
4751 bool success = false;
4752 const uint32_t opcode = OpcodeAsUnsigned (&success);
4753 if (!success)
4754 return false;
4755
4756 if (ConditionPassed())
4757 {
4758 uint32_t Rd;
4759 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
4760 bool add;
4761 switch (encoding)
4762 {
4763 case eEncodingT1:
4764 Rd = Bits32(opcode, 10, 8);
4765 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
4766 break;
4767 case eEncodingT2:
4768 case eEncodingT3:
4769 Rd = Bits32(opcode, 11, 8);
4770 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
4771 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
4772 if (BadReg(Rd))
4773 return false;
4774 break;
4775 case eEncodingA1:
4776 case eEncodingA2:
4777 Rd = Bits32(opcode, 15, 12);
4778 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4779 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
4780 break;
4781 default:
4782 return false;
4783 }
4784
4785 // Read the PC value.
4786 uint32_t pc = ReadCoreReg(PC_REG, &success);
4787 if (!success)
4788 return false;
4789
4790 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
4791
4792 EmulateInstruction::Context context;
4793 context.type = EmulateInstruction::eContextImmediate;
4794 context.SetNoArgs ();
4795
4796 if (!WriteCoreReg(context, result, Rd))
4797 return false;
4798 }
4799 return true;
4800}
4801
Johnny Chene97c0d52011-02-18 19:32:20 +00004802// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4803// to the destination register. It can optionally update the condition flags based on the result.
4804bool
4805EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4806{
4807#if 0
4808 // ARM pseudo code...
4809 if ConditionPassed() then
4810 EncodingSpecificOperations();
4811 result = R[n] AND imm32;
4812 if d == 15 then // Can only occur for ARM encoding
4813 ALUWritePC(result); // setflags is always FALSE here
4814 else
4815 R[d] = result;
4816 if setflags then
4817 APSR.N = result<31>;
4818 APSR.Z = IsZeroBit(result);
4819 APSR.C = carry;
4820 // APSR.V unchanged
4821#endif
4822
4823 bool success = false;
4824 const uint32_t opcode = OpcodeAsUnsigned (&success);
4825 if (!success)
4826 return false;
4827
4828 if (ConditionPassed())
4829 {
4830 uint32_t Rd, Rn;
4831 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4832 bool setflags;
4833 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4834 switch (encoding)
4835 {
4836 case eEncodingT1:
4837 Rd = Bits32(opcode, 11, 8);
4838 Rn = Bits32(opcode, 19, 16);
4839 setflags = BitIsSet(opcode, 20);
4840 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004841 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004842 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004843 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004844 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4845 return false;
4846 break;
4847 case eEncodingA1:
4848 Rd = Bits32(opcode, 15, 12);
4849 Rn = Bits32(opcode, 19, 16);
4850 setflags = BitIsSet(opcode, 20);
4851 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4852 // TODO: Emulate SUBS PC, LR and related instructions.
4853 if (Rd == 15 && setflags)
4854 return false;
4855 break;
4856 default:
4857 return false;
4858 }
4859
Johnny Chene97c0d52011-02-18 19:32:20 +00004860 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004861 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004862 if (!success)
4863 return false;
4864
4865 uint32_t result = val1 & imm32;
4866
4867 EmulateInstruction::Context context;
4868 context.type = EmulateInstruction::eContextImmediate;
4869 context.SetNoArgs ();
4870
4871 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4872 return false;
4873 }
4874 return true;
4875}
4876
4877// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4878// and writes the result to the destination register. It can optionally update the condition flags
4879// based on the result.
4880bool
4881EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4882{
4883#if 0
4884 // ARM pseudo code...
4885 if ConditionPassed() then
4886 EncodingSpecificOperations();
4887 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4888 result = R[n] AND shifted;
4889 if d == 15 then // Can only occur for ARM encoding
4890 ALUWritePC(result); // setflags is always FALSE here
4891 else
4892 R[d] = result;
4893 if setflags then
4894 APSR.N = result<31>;
4895 APSR.Z = IsZeroBit(result);
4896 APSR.C = carry;
4897 // APSR.V unchanged
4898#endif
4899
4900 bool success = false;
4901 const uint32_t opcode = OpcodeAsUnsigned (&success);
4902 if (!success)
4903 return false;
4904
4905 if (ConditionPassed())
4906 {
4907 uint32_t Rd, Rn, Rm;
4908 ARM_ShifterType shift_t;
4909 uint32_t shift_n; // the shift applied to the value read from Rm
4910 bool setflags;
4911 uint32_t carry;
4912 switch (encoding)
4913 {
4914 case eEncodingT1:
4915 Rd = Rn = Bits32(opcode, 2, 0);
4916 Rm = Bits32(opcode, 5, 3);
4917 setflags = !InITBlock();
4918 shift_t = SRType_LSL;
4919 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004920 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004921 case eEncodingT2:
4922 Rd = Bits32(opcode, 11, 8);
4923 Rn = Bits32(opcode, 19, 16);
4924 Rm = Bits32(opcode, 3, 0);
4925 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004926 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004927 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004928 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004929 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004930 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4931 return false;
4932 break;
4933 case eEncodingA1:
4934 Rd = Bits32(opcode, 15, 12);
4935 Rn = Bits32(opcode, 19, 16);
4936 Rm = Bits32(opcode, 3, 0);
4937 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004938 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004939 // TODO: Emulate SUBS PC, LR and related instructions.
4940 if (Rd == 15 && setflags)
4941 return false;
4942 break;
4943 default:
4944 return false;
4945 }
4946
Johnny Chene97c0d52011-02-18 19:32:20 +00004947 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004948 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004949 if (!success)
4950 return false;
4951
4952 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004953 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004954 if (!success)
4955 return false;
4956
4957 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4958 uint32_t result = val1 & shifted;
4959
4960 EmulateInstruction::Context context;
4961 context.type = EmulateInstruction::eContextImmediate;
4962 context.SetNoArgs ();
4963
4964 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4965 return false;
4966 }
4967 return true;
4968}
4969
Johnny Chenb9f02cf2011-02-24 01:15:17 +00004970// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
4971// immediate value, and writes the result to the destination register. It can optionally update the
4972// condition flags based on the result.
4973bool
4974EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
4975{
4976#if 0
4977 // ARM pseudo code...
4978 if ConditionPassed() then
4979 EncodingSpecificOperations();
4980 result = R[n] AND NOT(imm32);
4981 if d == 15 then // Can only occur for ARM encoding
4982 ALUWritePC(result); // setflags is always FALSE here
4983 else
4984 R[d] = result;
4985 if setflags then
4986 APSR.N = result<31>;
4987 APSR.Z = IsZeroBit(result);
4988 APSR.C = carry;
4989 // APSR.V unchanged
4990#endif
4991
4992 bool success = false;
4993 const uint32_t opcode = OpcodeAsUnsigned (&success);
4994 if (!success)
4995 return false;
4996
4997 if (ConditionPassed())
4998 {
4999 uint32_t Rd, Rn;
5000 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5001 bool setflags;
5002 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5003 switch (encoding)
5004 {
5005 case eEncodingT1:
5006 Rd = Bits32(opcode, 11, 8);
5007 Rn = Bits32(opcode, 19, 16);
5008 setflags = BitIsSet(opcode, 20);
5009 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5010 if (BadReg(Rd) || BadReg(Rn))
5011 return false;
5012 break;
5013 case eEncodingA1:
5014 Rd = Bits32(opcode, 15, 12);
5015 Rn = Bits32(opcode, 19, 16);
5016 setflags = BitIsSet(opcode, 20);
5017 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5018 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5019 // TODO: Emulate SUBS PC, LR and related instructions.
5020 if (Rd == 15 && setflags)
5021 return false;
5022 break;
5023 default:
5024 return false;
5025 }
5026
5027 // Read the first operand.
5028 uint32_t val1 = ReadCoreReg(Rn, &success);
5029 if (!success)
5030 return false;
5031
5032 uint32_t result = val1 & ~imm32;
5033
5034 EmulateInstruction::Context context;
5035 context.type = EmulateInstruction::eContextImmediate;
5036 context.SetNoArgs ();
5037
5038 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5039 return false;
5040 }
5041 return true;
5042}
5043
5044// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5045// optionally-shifted register value, and writes the result to the destination register.
5046// It can optionally update the condition flags based on the result.
5047bool
5048EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5049{
5050#if 0
5051 // ARM pseudo code...
5052 if ConditionPassed() then
5053 EncodingSpecificOperations();
5054 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5055 result = R[n] AND NOT(shifted);
5056 if d == 15 then // Can only occur for ARM encoding
5057 ALUWritePC(result); // setflags is always FALSE here
5058 else
5059 R[d] = result;
5060 if setflags then
5061 APSR.N = result<31>;
5062 APSR.Z = IsZeroBit(result);
5063 APSR.C = carry;
5064 // APSR.V unchanged
5065#endif
5066
5067 bool success = false;
5068 const uint32_t opcode = OpcodeAsUnsigned (&success);
5069 if (!success)
5070 return false;
5071
5072 if (ConditionPassed())
5073 {
5074 uint32_t Rd, Rn, Rm;
5075 ARM_ShifterType shift_t;
5076 uint32_t shift_n; // the shift applied to the value read from Rm
5077 bool setflags;
5078 uint32_t carry;
5079 switch (encoding)
5080 {
5081 case eEncodingT1:
5082 Rd = Rn = Bits32(opcode, 2, 0);
5083 Rm = Bits32(opcode, 5, 3);
5084 setflags = !InITBlock();
5085 shift_t = SRType_LSL;
5086 shift_n = 0;
5087 break;
5088 case eEncodingT2:
5089 Rd = Bits32(opcode, 11, 8);
5090 Rn = Bits32(opcode, 19, 16);
5091 Rm = Bits32(opcode, 3, 0);
5092 setflags = BitIsSet(opcode, 20);
5093 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5094 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5095 return false;
5096 break;
5097 case eEncodingA1:
5098 Rd = Bits32(opcode, 15, 12);
5099 Rn = Bits32(opcode, 19, 16);
5100 Rm = Bits32(opcode, 3, 0);
5101 setflags = BitIsSet(opcode, 20);
5102 shift_n = DecodeImmShiftARM(opcode, shift_t);
5103 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5104 // TODO: Emulate SUBS PC, LR and related instructions.
5105 if (Rd == 15 && setflags)
5106 return false;
5107 break;
5108 default:
5109 return false;
5110 }
5111
5112 // Read the first operand.
5113 uint32_t val1 = ReadCoreReg(Rn, &success);
5114 if (!success)
5115 return false;
5116
5117 // Read the second operand.
5118 uint32_t val2 = ReadCoreReg(Rm, &success);
5119 if (!success)
5120 return false;
5121
5122 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5123 uint32_t result = val1 & ~shifted;
5124
5125 EmulateInstruction::Context context;
5126 context.type = EmulateInstruction::eContextImmediate;
5127 context.SetNoArgs ();
5128
5129 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5130 return false;
5131 }
5132 return true;
5133}
5134
Caroline Tice4d729c52011-02-18 00:55:53 +00005135// 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 +00005136// 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 +00005137bool
5138EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5139{
5140#if 0
5141 if ConditionPassed() then
5142 EncodingSpecificOperations();
5143 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5144 address = if index then offset_addr else R[n];
5145 data = MemU[address,4];
5146 if wback then R[n] = offset_addr;
5147 if t == 15 then
5148 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5149 elsif UnalignedSupport() || address<1:0> = ’00’ then
5150 R[t] = data;
5151 else // Can only apply before ARMv7
5152 R[t] = ROR(data, 8*UInt(address<1:0>));
5153#endif
5154
5155 bool success = false;
5156 const uint32_t opcode = OpcodeAsUnsigned (&success);
5157 if (!success)
5158 return false;
5159
5160 if (ConditionPassed ())
5161 {
5162 const uint32_t addr_byte_size = GetAddressByteSize();
5163
5164 uint32_t t;
5165 uint32_t n;
5166 uint32_t imm32;
5167 bool index;
5168 bool add;
5169 bool wback;
5170
5171 switch (encoding)
5172 {
5173 case eEncodingA1:
5174 // if Rn == ’1111’ then SEE LDR (literal);
5175 // if P == ’0’ && W == ’1’ then SEE LDRT;
5176 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5177 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5178 t = Bits32 (opcode, 15, 12);
5179 n = Bits32 (opcode, 19, 16);
5180 imm32 = Bits32 (opcode, 11, 0);
5181
5182 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5183 index = BitIsSet (opcode, 24);
5184 add = BitIsSet (opcode, 23);
5185 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5186
5187 // if wback && n == t then UNPREDICTABLE;
5188 if (wback && (n == t))
5189 return false;
5190
5191 break;
5192
5193 default:
5194 return false;
5195 }
5196
5197 addr_t address;
5198 addr_t offset_addr;
5199 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5200 if (!success)
5201 return false;
5202
5203 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5204 if (add)
5205 offset_addr = base_address + imm32;
5206 else
5207 offset_addr = base_address - imm32;
5208
5209 // address = if index then offset_addr else R[n];
5210 if (index)
5211 address = offset_addr;
5212 else
5213 address = base_address;
5214
5215 // data = MemU[address,4];
5216
5217 Register base_reg;
5218 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5219
5220 EmulateInstruction::Context context;
5221 context.type = eContextRegisterLoad;
5222 context.SetRegisterPlusOffset (base_reg, address - base_address);
5223
5224 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5225 if (!success)
5226 return false;
5227
5228 // if wback then R[n] = offset_addr;
5229 if (wback)
5230 {
5231 context.type = eContextAdjustBaseRegister;
5232 context.SetAddress (offset_addr);
5233 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5234 return false;
5235 }
5236
5237 // if t == 15 then
5238 if (t == 15)
5239 {
5240 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5241 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5242 {
5243 // LoadWritePC (data);
5244 context.type = eContextRegisterLoad;
5245 context.SetRegisterPlusOffset (base_reg, address - base_address);
5246 LoadWritePC (context, data);
5247 }
5248 else
5249 return false;
5250 }
5251 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5252 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5253 {
5254 // R[t] = data;
5255 context.type = eContextRegisterLoad;
5256 context.SetRegisterPlusOffset (base_reg, address - base_address);
5257 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5258 return false;
5259 }
5260 // else // Can only apply before ARMv7
5261 else
5262 {
5263 // R[t] = ROR(data, 8*UInt(address<1:0>));
5264 data = ROR (data, Bits32 (address, 1, 0));
5265 context.type = eContextRegisterLoad;
5266 context.SetImmediate (data);
5267 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5268 return false;
5269 }
5270
5271 }
5272 return true;
5273}
5274
Caroline Ticefe479112011-02-18 18:52:37 +00005275// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5276// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5277bool
5278EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5279{
5280#if 0
5281 if ConditionPassed() then
5282 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5283 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5284 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5285 address = if index then offset_addr else R[n];
5286 data = MemU[address,4];
5287 if wback then R[n] = offset_addr;
5288 if t == 15 then
5289 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5290 elsif UnalignedSupport() || address<1:0> = ’00’ then
5291 R[t] = data;
5292 else // Can only apply before ARMv7
5293 if CurrentInstrSet() == InstrSet_ARM then
5294 R[t] = ROR(data, 8*UInt(address<1:0>));
5295 else
5296 R[t] = bits(32) UNKNOWN;
5297#endif
5298
5299 bool success = false;
5300 const uint32_t opcode = OpcodeAsUnsigned (&success);
5301 if (!success)
5302 return false;
5303
5304 if (ConditionPassed ())
5305 {
5306 const uint32_t addr_byte_size = GetAddressByteSize();
5307
5308 uint32_t t;
5309 uint32_t n;
5310 uint32_t m;
5311 bool index;
5312 bool add;
5313 bool wback;
5314 ARM_ShifterType shift_t;
5315 uint32_t shift_n;
5316
5317 switch (encoding)
5318 {
5319 case eEncodingT1:
5320 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5321 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5322 t = Bits32 (opcode, 2, 0);
5323 n = Bits32 (opcode, 5, 3);
5324 m = Bits32 (opcode, 8, 6);
5325
5326 // index = TRUE; add = TRUE; wback = FALSE;
5327 index = true;
5328 add = true;
5329 wback = false;
5330
5331 // (shift_t, shift_n) = (SRType_LSL, 0);
5332 shift_t = SRType_LSL;
5333 shift_n = 0;
5334
5335 break;
5336
5337 case eEncodingT2:
5338 // if Rn == ’1111’ then SEE LDR (literal);
5339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5340 t = Bits32 (opcode, 15, 12);
5341 n = Bits32 (opcode, 19, 16);
5342 m = Bits32 (opcode, 3, 0);
5343
5344 // index = TRUE; add = TRUE; wback = FALSE;
5345 index = true;
5346 add = true;
5347 wback = false;
5348
5349 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5350 shift_t = SRType_LSL;
5351 shift_n = Bits32 (opcode, 5, 4);
5352
5353 // if BadReg(m) then UNPREDICTABLE;
5354 if (BadReg (m))
5355 return false;
5356
5357 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5358 if ((t == 15) && InITBlock() && !LastInITBlock())
5359 return false;
5360
5361 break;
5362
5363 case eEncodingA1:
5364 {
5365 // if P == ’0’ && W == ’1’ then SEE LDRT;
5366 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5367 t = Bits32 (opcode, 15, 12);
5368 n = Bits32 (opcode, 19, 16);
5369 m = Bits32 (opcode, 3, 0);
5370
5371 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5372 index = BitIsSet (opcode, 24);
5373 add = BitIsSet (opcode, 23);
5374 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5375
5376 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5377 uint32_t type = Bits32 (opcode, 6, 5);
5378 uint32_t imm5 = Bits32 (opcode, 11, 7);
5379 shift_n = DecodeImmShift (type, imm5, shift_t);
5380
5381 // if m == 15 then UNPREDICTABLE;
5382 if (m == 15)
5383 return false;
5384
5385 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5386 if (wback && ((n == 15) || (n == t)))
5387 return false;
5388 }
5389 break;
5390
5391
5392 default:
5393 return false;
5394 }
5395
5396 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5397 if (!success)
5398 return false;
5399
5400 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5401 if (!success)
5402 return false;
5403
5404 addr_t offset_addr;
5405 addr_t address;
5406
5407 // 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 +00005408 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005409
5410 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5411 if (add)
5412 offset_addr = Rn + offset;
5413 else
5414 offset_addr = Rn - offset;
5415
5416 // address = if index then offset_addr else R[n];
5417 if (index)
5418 address = offset_addr;
5419 else
5420 address = Rn;
5421
5422 // data = MemU[address,4];
5423 Register base_reg;
5424 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5425
5426 EmulateInstruction::Context context;
5427 context.type = eContextRegisterLoad;
5428 context.SetRegisterPlusOffset (base_reg, address - Rn);
5429
5430 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5431 if (!success)
5432 return false;
5433
5434 // if wback then R[n] = offset_addr;
5435 if (wback)
5436 {
5437 context.type = eContextAdjustBaseRegister;
5438 context.SetAddress (offset_addr);
5439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5440 return false;
5441 }
5442
5443 // if t == 15 then
5444 if (t == 15)
5445 {
5446 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5447 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5448 {
5449 context.type = eContextRegisterLoad;
5450 context.SetRegisterPlusOffset (base_reg, address - Rn);
5451 LoadWritePC (context, data);
5452 }
5453 else
5454 return false;
5455 }
5456 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5457 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5458 {
5459 // R[t] = data;
5460 context.type = eContextRegisterLoad;
5461 context.SetRegisterPlusOffset (base_reg, address - Rn);
5462 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5463 return false;
5464 }
5465 else // Can only apply before ARMv7
5466 {
5467 // if CurrentInstrSet() == InstrSet_ARM then
5468 if (CurrentInstrSet () == eModeARM)
5469 {
5470 // R[t] = ROR(data, 8*UInt(address<1:0>));
5471 data = ROR (data, Bits32 (address, 1, 0));
5472 context.type = eContextRegisterLoad;
5473 context.SetImmediate (data);
5474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5475 return false;
5476 }
5477 else
5478 {
5479 // R[t] = bits(32) UNKNOWN;
5480 WriteBits32Unknown (t);
5481 }
5482 }
5483 }
5484 return true;
5485}
Caroline Tice21b604b2011-02-18 21:06:04 +00005486
5487// LDRB (immediate, Thumb)
5488bool
5489EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5490{
5491#if 0
5492 if ConditionPassed() then
5493 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5494 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5495 address = if index then offset_addr else R[n];
5496 R[t] = ZeroExtend(MemU[address,1], 32);
5497 if wback then R[n] = offset_addr;
5498#endif
5499
5500 bool success = false;
5501 const uint32_t opcode = OpcodeAsUnsigned (&success);
5502 if (!success)
5503 return false;
5504
5505 if (ConditionPassed ())
5506 {
5507 uint32_t t;
5508 uint32_t n;
5509 uint32_t imm32;
5510 bool index;
5511 bool add;
5512 bool wback;
5513
5514 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5515 switch (encoding)
5516 {
5517 case eEncodingT1:
5518 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5519 t = Bits32 (opcode, 2, 0);
5520 n = Bits32 (opcode, 5, 3);
5521 imm32 = Bits32 (opcode, 10, 6);
5522
5523 // index = TRUE; add = TRUE; wback = FALSE;
5524 index = true;
5525 add = true;
5526 wback= false;
5527
5528 break;
5529
5530 case eEncodingT2:
5531 // if Rt == ’1111’ then SEE PLD;
5532 // if Rn == ’1111’ then SEE LDRB (literal);
5533 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5534 t = Bits32 (opcode, 15, 12);
5535 n = Bits32 (opcode, 19, 16);
5536 imm32 = Bits32 (opcode, 11, 0);
5537
5538 // index = TRUE; add = TRUE; wback = FALSE;
5539 index = true;
5540 add = true;
5541 wback = false;
5542
5543 // if t == 13 then UNPREDICTABLE;
5544 if (t == 13)
5545 return false;
5546
5547 break;
5548
5549 case eEncodingT3:
5550 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5551 // if Rn == ’1111’ then SEE LDRB (literal);
5552 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5553 // if P == ’0’ && W == ’0’ then UNDEFINED;
5554 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5555 return false;
5556
5557 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5558 t = Bits32 (opcode, 15, 12);
5559 n = Bits32 (opcode, 19, 16);
5560 imm32 = Bits32 (opcode, 7, 0);
5561
5562 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5563 index = BitIsSet (opcode, 10);
5564 add = BitIsSet (opcode, 9);
5565 wback = BitIsSet (opcode, 8);
5566
5567 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5568 if (BadReg (t) || (wback && (n == t)))
5569 return false;
5570
5571 break;
5572
5573 default:
5574 return false;
5575 }
5576
5577 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5578 if (!success)
5579 return false;
5580
5581 addr_t address;
5582 addr_t offset_addr;
5583
5584 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5585 if (add)
5586 offset_addr = Rn + imm32;
5587 else
5588 offset_addr = Rn - imm32;
5589
5590 // address = if index then offset_addr else R[n];
5591 if (index)
5592 address = offset_addr;
5593 else
5594 address = Rn;
5595
5596 // R[t] = ZeroExtend(MemU[address,1], 32);
5597 Register base_reg;
5598 Register data_reg;
5599 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5600 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5601
5602 EmulateInstruction::Context context;
5603 context.type = eContextRegisterLoad;
5604 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5605
5606 uint64_t data = MemURead (context, address, 1, 0, &success);
5607 if (!success)
5608 return false;
5609
5610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5611 return false;
5612
5613 // if wback then R[n] = offset_addr;
5614 if (wback)
5615 {
5616 context.type = eContextAdjustBaseRegister;
5617 context.SetAddress (offset_addr);
5618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5619 return false;
5620 }
5621 }
5622 return true;
5623}
Caroline Ticef55261f2011-02-18 22:24:22 +00005624
5625// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5626// zero-extends it to form a 32-bit word and writes it to a register.
5627bool
5628EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5629{
5630#if 0
5631 if ConditionPassed() then
5632 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5633 base = Align(PC,4);
5634 address = if add then (base + imm32) else (base - imm32);
5635 R[t] = ZeroExtend(MemU[address,1], 32);
5636#endif
5637
5638 bool success = false;
5639 const uint32_t opcode = OpcodeAsUnsigned (&success);
5640 if (!success)
5641 return false;
5642
5643 if (ConditionPassed ())
5644 {
5645 uint32_t t;
5646 uint32_t imm32;
5647 bool add;
5648 switch (encoding)
5649 {
5650 case eEncodingT1:
5651 // if Rt == ’1111’ then SEE PLD;
5652 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5653 t = Bits32 (opcode, 15, 12);
5654 imm32 = Bits32 (opcode, 11, 0);
5655 add = BitIsSet (opcode, 23);
5656
5657 // if t == 13 then UNPREDICTABLE;
5658 if (t == 13)
5659 return false;
5660
5661 break;
5662
5663 case eEncodingA1:
5664 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5665 t = Bits32 (opcode, 15, 12);
5666 imm32 = Bits32 (opcode, 11, 0);
5667 add = BitIsSet (opcode, 23);
5668
5669 // if t == 15 then UNPREDICTABLE;
5670 if (t == 15)
5671 return false;
5672 break;
5673
5674 default:
5675 return false;
5676 }
5677
5678 // base = Align(PC,4);
5679 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5680 if (!success)
5681 return false;
5682
5683 uint32_t base = AlignPC (pc_val);
5684
5685 addr_t address;
5686 // address = if add then (base + imm32) else (base - imm32);
5687 if (add)
5688 address = base + imm32;
5689 else
5690 address = base - imm32;
5691
5692 // R[t] = ZeroExtend(MemU[address,1], 32);
5693 EmulateInstruction::Context context;
5694 context.type = eContextRelativeBranchImmediate;
5695 context.SetImmediate (address - base);
5696
5697 uint64_t data = MemURead (context, address, 1, 0, &success);
5698 if (!success)
5699 return false;
5700
5701 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5702 return false;
5703 }
5704 return true;
5705}
Caroline Tice30fec122011-02-18 23:52:21 +00005706
5707// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5708// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5709// optionally be shifted.
5710bool
5711EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5712{
5713#if 0
5714 if ConditionPassed() then
5715 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5716 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5717 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5718 address = if index then offset_addr else R[n];
5719 R[t] = ZeroExtend(MemU[address,1],32);
5720 if wback then R[n] = offset_addr;
5721#endif
5722
5723 bool success = false;
5724 const uint32_t opcode = OpcodeAsUnsigned (&success);
5725 if (!success)
5726 return false;
5727
5728 if (ConditionPassed ())
5729 {
5730 uint32_t t;
5731 uint32_t n;
5732 uint32_t m;
5733 bool index;
5734 bool add;
5735 bool wback;
5736 ARM_ShifterType shift_t;
5737 uint32_t shift_n;
5738
5739 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5740 switch (encoding)
5741 {
5742 case eEncodingT1:
5743 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5744 t = Bits32 (opcode, 2, 0);
5745 n = Bits32 (opcode, 5, 3);
5746 m = Bits32 (opcode, 8, 6);
5747
5748 // index = TRUE; add = TRUE; wback = FALSE;
5749 index = true;
5750 add = true;
5751 wback = false;
5752
5753 // (shift_t, shift_n) = (SRType_LSL, 0);
5754 shift_t = SRType_LSL;
5755 shift_n = 0;
5756 break;
5757
5758 case eEncodingT2:
5759 // if Rt == ’1111’ then SEE PLD;
5760 // if Rn == ’1111’ then SEE LDRB (literal);
5761 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5762 t = Bits32 (opcode, 15, 12);
5763 n = Bits32 (opcode, 19, 16);
5764 m = Bits32 (opcode, 3, 0);
5765
5766 // index = TRUE; add = TRUE; wback = FALSE;
5767 index = true;
5768 add = true;
5769 wback = false;
5770
5771 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5772 shift_t = SRType_LSL;
5773 shift_n = Bits32 (opcode, 5, 4);
5774
5775 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5776 if ((t == 13) || BadReg (m))
5777 return false;
5778 break;
5779
5780 case eEncodingA1:
5781 {
5782 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5783 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5784 t = Bits32 (opcode, 15, 12);
5785 n = Bits32 (opcode, 19, 16);
5786 m = Bits32 (opcode, 3, 0);
5787
5788 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5789 index = BitIsSet (opcode, 24);
5790 add = BitIsSet (opcode, 23);
5791 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5792
5793 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5794 uint32_t type = Bits32 (opcode, 6, 5);
5795 uint32_t imm5 = Bits32 (opcode, 11, 7);
5796 shift_n = DecodeImmShift (type, imm5, shift_t);
5797
5798 // if t == 15 || m == 15 then UNPREDICTABLE;
5799 if ((t == 15) || (m == 15))
5800 return false;
5801
5802 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5803 if (wback && ((n == 15) || (n == t)))
5804 return false;
5805 }
5806 break;
5807
5808 default:
5809 return false;
5810 }
5811
5812 addr_t offset_addr;
5813 addr_t address;
5814
5815 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5816 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5817 if (!success)
5818 return false;
5819
5820 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5821
5822 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5823 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5824 if (!success)
5825 return false;
5826
5827 if (add)
5828 offset_addr = Rn + offset;
5829 else
5830 offset_addr = Rn - offset;
5831
5832 // address = if index then offset_addr else R[n];
5833 if (index)
5834 address = offset_addr;
5835 else
5836 address = Rn;
5837
5838 // R[t] = ZeroExtend(MemU[address,1],32);
5839 Register base_reg;
5840 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5841
5842 EmulateInstruction::Context context;
5843 context.type = eContextRegisterLoad;
5844 context.SetRegisterPlusOffset (base_reg, address - Rn);
5845
5846 uint64_t data = MemURead (context, address, 1, 0, &success);
5847 if (!success)
5848 return false;
5849
5850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5851 return false;
5852
5853 // if wback then R[n] = offset_addr;
5854 if (wback)
5855 {
5856 context.type = eContextAdjustBaseRegister;
5857 context.SetAddress (offset_addr);
5858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5859 return false;
5860 }
5861 }
5862 return true;
5863}
Caroline Ticefe479112011-02-18 18:52:37 +00005864
Johnny Chen2115b412011-02-21 23:42:44 +00005865// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5866// and writes the result to the destination register. It can optionally update the condition flags based on
5867// the result.
5868bool
5869EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5870{
5871#if 0
5872 // ARM pseudo code...
5873 if ConditionPassed() then
5874 EncodingSpecificOperations();
5875 result = R[n] EOR imm32;
5876 if d == 15 then // Can only occur for ARM encoding
5877 ALUWritePC(result); // setflags is always FALSE here
5878 else
5879 R[d] = result;
5880 if setflags then
5881 APSR.N = result<31>;
5882 APSR.Z = IsZeroBit(result);
5883 APSR.C = carry;
5884 // APSR.V unchanged
5885#endif
5886
5887 bool success = false;
5888 const uint32_t opcode = OpcodeAsUnsigned (&success);
5889 if (!success)
5890 return false;
5891
5892 if (ConditionPassed())
5893 {
5894 uint32_t Rd, Rn;
5895 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5896 bool setflags;
5897 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5898 switch (encoding)
5899 {
5900 case eEncodingT1:
5901 Rd = Bits32(opcode, 11, 8);
5902 Rn = Bits32(opcode, 19, 16);
5903 setflags = BitIsSet(opcode, 20);
5904 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5905 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5906 if (Rd == 15 && setflags)
5907 return EmulateTEQImm(eEncodingT1);
5908 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5909 return false;
5910 break;
5911 case eEncodingA1:
5912 Rd = Bits32(opcode, 15, 12);
5913 Rn = Bits32(opcode, 19, 16);
5914 setflags = BitIsSet(opcode, 20);
5915 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5916 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5917 // TODO: Emulate SUBS PC, LR and related instructions.
5918 if (Rd == 15 && setflags)
5919 return false;
5920 break;
5921 default:
5922 return false;
5923 }
5924
5925 // Read the first operand.
5926 uint32_t val1 = ReadCoreReg(Rn, &success);
5927 if (!success)
5928 return false;
5929
5930 uint32_t result = val1 ^ imm32;
5931
5932 EmulateInstruction::Context context;
5933 context.type = EmulateInstruction::eContextImmediate;
5934 context.SetNoArgs ();
5935
5936 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5937 return false;
5938 }
5939 return true;
5940}
5941
5942// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5943// optionally-shifted register value, and writes the result to the destination register.
5944// It can optionally update the condition flags based on the result.
5945bool
5946EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5947{
5948#if 0
5949 // ARM pseudo code...
5950 if ConditionPassed() then
5951 EncodingSpecificOperations();
5952 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5953 result = R[n] EOR shifted;
5954 if d == 15 then // Can only occur for ARM encoding
5955 ALUWritePC(result); // setflags is always FALSE here
5956 else
5957 R[d] = result;
5958 if setflags then
5959 APSR.N = result<31>;
5960 APSR.Z = IsZeroBit(result);
5961 APSR.C = carry;
5962 // APSR.V unchanged
5963#endif
5964
5965 bool success = false;
5966 const uint32_t opcode = OpcodeAsUnsigned (&success);
5967 if (!success)
5968 return false;
5969
5970 if (ConditionPassed())
5971 {
5972 uint32_t Rd, Rn, Rm;
5973 ARM_ShifterType shift_t;
5974 uint32_t shift_n; // the shift applied to the value read from Rm
5975 bool setflags;
5976 uint32_t carry;
5977 switch (encoding)
5978 {
5979 case eEncodingT1:
5980 Rd = Rn = Bits32(opcode, 2, 0);
5981 Rm = Bits32(opcode, 5, 3);
5982 setflags = !InITBlock();
5983 shift_t = SRType_LSL;
5984 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005985 break;
Johnny Chen2115b412011-02-21 23:42:44 +00005986 case eEncodingT2:
5987 Rd = Bits32(opcode, 11, 8);
5988 Rn = Bits32(opcode, 19, 16);
5989 Rm = Bits32(opcode, 3, 0);
5990 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005991 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5992 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005993 if (Rd == 15 && setflags)
5994 return EmulateTEQReg(eEncodingT1);
5995 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5996 return false;
5997 break;
5998 case eEncodingA1:
5999 Rd = Bits32(opcode, 15, 12);
6000 Rn = Bits32(opcode, 19, 16);
6001 Rm = Bits32(opcode, 3, 0);
6002 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006003 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006004 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6005 // TODO: Emulate SUBS PC, LR and related instructions.
6006 if (Rd == 15 && setflags)
6007 return false;
6008 break;
6009 default:
6010 return false;
6011 }
6012
6013 // Read the first operand.
6014 uint32_t val1 = ReadCoreReg(Rn, &success);
6015 if (!success)
6016 return false;
6017
6018 // Read the second operand.
6019 uint32_t val2 = ReadCoreReg(Rm, &success);
6020 if (!success)
6021 return false;
6022
6023 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6024 uint32_t result = val1 ^ shifted;
6025
6026 EmulateInstruction::Context context;
6027 context.type = EmulateInstruction::eContextImmediate;
6028 context.SetNoArgs ();
6029
6030 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6031 return false;
6032 }
6033 return true;
6034}
6035
Johnny Chen7c5234d2011-02-18 23:41:11 +00006036// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
6037// writes the result to the destination register. It can optionally update the condition flags based
6038// on the result.
6039bool
6040EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
6041{
6042#if 0
6043 // ARM pseudo code...
6044 if ConditionPassed() then
6045 EncodingSpecificOperations();
6046 result = R[n] OR imm32;
6047 if d == 15 then // Can only occur for ARM encoding
6048 ALUWritePC(result); // setflags is always FALSE here
6049 else
6050 R[d] = result;
6051 if setflags then
6052 APSR.N = result<31>;
6053 APSR.Z = IsZeroBit(result);
6054 APSR.C = carry;
6055 // APSR.V unchanged
6056#endif
6057
6058 bool success = false;
6059 const uint32_t opcode = OpcodeAsUnsigned (&success);
6060 if (!success)
6061 return false;
6062
6063 if (ConditionPassed())
6064 {
6065 uint32_t Rd, Rn;
6066 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
6067 bool setflags;
6068 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6069 switch (encoding)
6070 {
6071 case eEncodingT1:
6072 Rd = Bits32(opcode, 11, 8);
6073 Rn = Bits32(opcode, 19, 16);
6074 setflags = BitIsSet(opcode, 20);
6075 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6076 // if Rn == ‘1111’ then SEE MOV (immediate);
6077 if (Rn == 15)
6078 return EmulateMOVRdImm(eEncodingT2);
6079 if (BadReg(Rd) || Rn == 13)
6080 return false;
6081 break;
6082 case eEncodingA1:
6083 Rd = Bits32(opcode, 15, 12);
6084 Rn = Bits32(opcode, 19, 16);
6085 setflags = BitIsSet(opcode, 20);
6086 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6087 // TODO: Emulate SUBS PC, LR and related instructions.
6088 if (Rd == 15 && setflags)
6089 return false;
6090 break;
6091 default:
6092 return false;
6093 }
6094
6095 // Read the first operand.
6096 uint32_t val1 = ReadCoreReg(Rn, &success);
6097 if (!success)
6098 return false;
6099
6100 uint32_t result = val1 | imm32;
6101
6102 EmulateInstruction::Context context;
6103 context.type = EmulateInstruction::eContextImmediate;
6104 context.SetNoArgs ();
6105
6106 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6107 return false;
6108 }
6109 return true;
6110}
6111
6112// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
6113// value, and writes the result to the destination register. It can optionally update the condition flags based
6114// on the result.
6115bool
6116EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
6117{
6118#if 0
6119 // ARM pseudo code...
6120 if ConditionPassed() then
6121 EncodingSpecificOperations();
6122 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6123 result = R[n] OR shifted;
6124 if d == 15 then // Can only occur for ARM encoding
6125 ALUWritePC(result); // setflags is always FALSE here
6126 else
6127 R[d] = result;
6128 if setflags then
6129 APSR.N = result<31>;
6130 APSR.Z = IsZeroBit(result);
6131 APSR.C = carry;
6132 // APSR.V unchanged
6133#endif
6134
6135 bool success = false;
6136 const uint32_t opcode = OpcodeAsUnsigned (&success);
6137 if (!success)
6138 return false;
6139
6140 if (ConditionPassed())
6141 {
6142 uint32_t Rd, Rn, Rm;
6143 ARM_ShifterType shift_t;
6144 uint32_t shift_n; // the shift applied to the value read from Rm
6145 bool setflags;
6146 uint32_t carry;
6147 switch (encoding)
6148 {
6149 case eEncodingT1:
6150 Rd = Rn = Bits32(opcode, 2, 0);
6151 Rm = Bits32(opcode, 5, 3);
6152 setflags = !InITBlock();
6153 shift_t = SRType_LSL;
6154 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006155 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00006156 case eEncodingT2:
6157 Rd = Bits32(opcode, 11, 8);
6158 Rn = Bits32(opcode, 19, 16);
6159 Rm = Bits32(opcode, 3, 0);
6160 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006161 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6162 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00006163 if (Rn == 15)
6164 return EmulateMOVRdRm(eEncodingT3);
6165 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
6166 return false;
6167 break;
6168 case eEncodingA1:
6169 Rd = Bits32(opcode, 15, 12);
6170 Rn = Bits32(opcode, 19, 16);
6171 Rm = Bits32(opcode, 3, 0);
6172 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006173 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00006174 // TODO: Emulate SUBS PC, LR and related instructions.
6175 if (Rd == 15 && setflags)
6176 return false;
6177 break;
6178 default:
6179 return false;
6180 }
6181
6182 // Read the first operand.
6183 uint32_t val1 = ReadCoreReg(Rn, &success);
6184 if (!success)
6185 return false;
6186
6187 // Read the second operand.
6188 uint32_t val2 = ReadCoreReg(Rm, &success);
6189 if (!success)
6190 return false;
6191
6192 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00006193 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00006194
6195 EmulateInstruction::Context context;
6196 context.type = EmulateInstruction::eContextImmediate;
6197 context.SetNoArgs ();
6198
6199 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6200 return false;
6201 }
6202 return true;
6203}
6204
Johnny Chened32e7c2011-02-22 23:42:58 +00006205// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
6206// the destination register. It can optionally update the condition flags based on the result.
6207bool
6208EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
6209{
6210#if 0
6211 // ARM pseudo code...
6212 if ConditionPassed() then
6213 EncodingSpecificOperations();
6214 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
6215 if d == 15 then // Can only occur for ARM encoding
6216 ALUWritePC(result); // setflags is always FALSE here
6217 else
6218 R[d] = result;
6219 if setflags then
6220 APSR.N = result<31>;
6221 APSR.Z = IsZeroBit(result);
6222 APSR.C = carry;
6223 APSR.V = overflow;
6224#endif
6225
6226 bool success = false;
6227 const uint32_t opcode = OpcodeAsUnsigned (&success);
6228 if (!success)
6229 return false;
6230
6231 uint32_t Rd; // the destination register
6232 uint32_t Rn; // the first operand
6233 bool setflags;
6234 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6235 switch (encoding) {
6236 case eEncodingT1:
6237 Rd = Bits32(opcode, 2, 0);
6238 Rn = Bits32(opcode, 5, 3);
6239 setflags = !InITBlock();
6240 imm32 = 0;
6241 break;
6242 case eEncodingT2:
6243 Rd = Bits32(opcode, 11, 8);
6244 Rn = Bits32(opcode, 19, 16);
6245 setflags = BitIsSet(opcode, 20);
6246 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6247 if (BadReg(Rd) || BadReg(Rn))
6248 return false;
6249 break;
6250 case eEncodingA1:
6251 Rd = Bits32(opcode, 15, 12);
6252 Rn = Bits32(opcode, 19, 16);
6253 setflags = BitIsSet(opcode, 20);
6254 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6255 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6256 // TODO: Emulate SUBS PC, LR and related instructions.
6257 if (Rd == 15 && setflags)
6258 return false;
6259 break;
6260 default:
6261 return false;
6262 }
6263 // Read the register value from the operand register Rn.
6264 uint32_t reg_val = ReadCoreReg(Rn, &success);
6265 if (!success)
6266 return false;
6267
6268 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
6269
6270 EmulateInstruction::Context context;
6271 context.type = EmulateInstruction::eContextImmediate;
6272 context.SetNoArgs ();
6273
6274 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6275 return false;
6276
6277 return true;
6278}
6279
6280// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
6281// result to the destination register. It can optionally update the condition flags based on the result.
6282bool
6283EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
6284{
6285#if 0
6286 // ARM pseudo code...
6287 if ConditionPassed() then
6288 EncodingSpecificOperations();
6289 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6290 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
6291 if d == 15 then // Can only occur for ARM encoding
6292 ALUWritePC(result); // setflags is always FALSE here
6293 else
6294 R[d] = result;
6295 if setflags then
6296 APSR.N = result<31>;
6297 APSR.Z = IsZeroBit(result);
6298 APSR.C = carry;
6299 APSR.V = overflow;
6300#endif
6301
6302 bool success = false;
6303 const uint32_t opcode = OpcodeAsUnsigned (&success);
6304 if (!success)
6305 return false;
6306
6307 uint32_t Rd; // the destination register
6308 uint32_t Rn; // the first operand
6309 uint32_t Rm; // the second operand
6310 bool setflags;
6311 ARM_ShifterType shift_t;
6312 uint32_t shift_n; // the shift applied to the value read from Rm
6313 switch (encoding) {
6314 case eEncodingT1:
6315 Rd = Bits32(opcode, 11, 8);
6316 Rn = Bits32(opcode, 19, 16);
6317 Rm = Bits32(opcode, 3, 0);
6318 setflags = BitIsSet(opcode, 20);
6319 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6320 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6321 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6322 return false;
6323 break;
6324 case eEncodingA1:
6325 Rd = Bits32(opcode, 15, 12);
6326 Rn = Bits32(opcode, 19, 16);
6327 Rm = Bits32(opcode, 3, 0);
6328 setflags = BitIsSet(opcode, 20);
6329 shift_n = DecodeImmShiftARM(opcode, shift_t);
6330 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6331 // TODO: Emulate SUBS PC, LR and related instructions.
6332 if (Rd == 15 && setflags)
6333 return false;
6334 break;
6335 default:
6336 return false;
6337 }
6338 // Read the register value from register Rn.
6339 uint32_t val1 = ReadCoreReg(Rn, &success);
6340 if (!success)
6341 return false;
6342
6343 // Read the register value from register Rm.
6344 uint32_t val2 = ReadCoreReg(Rm, &success);
6345 if (!success)
6346 return false;
6347
6348 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6349 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6350
6351 EmulateInstruction::Context context;
6352 context.type = EmulateInstruction::eContextImmediate;
6353 context.SetNoArgs();
6354 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6355 return false;
6356
6357 return true;
6358}
6359
Johnny Chen90e607b2011-02-23 00:07:09 +00006360// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
6361// an immediate value, and writes the result to the destination register. It can optionally update the condition
6362// flags based on the result.
6363bool
6364EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
6365{
6366#if 0
6367 // ARM pseudo code...
6368 if ConditionPassed() then
6369 EncodingSpecificOperations();
6370 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
6371 if d == 15 then
6372 ALUWritePC(result); // setflags is always FALSE here
6373 else
6374 R[d] = result;
6375 if setflags then
6376 APSR.N = result<31>;
6377 APSR.Z = IsZeroBit(result);
6378 APSR.C = carry;
6379 APSR.V = overflow;
6380#endif
6381
6382 bool success = false;
6383 const uint32_t opcode = OpcodeAsUnsigned (&success);
6384 if (!success)
6385 return false;
6386
6387 uint32_t Rd; // the destination register
6388 uint32_t Rn; // the first operand
6389 bool setflags;
6390 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6391 switch (encoding) {
6392 case eEncodingA1:
6393 Rd = Bits32(opcode, 15, 12);
6394 Rn = Bits32(opcode, 19, 16);
6395 setflags = BitIsSet(opcode, 20);
6396 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6397 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6398 // TODO: Emulate SUBS PC, LR and related instructions.
6399 if (Rd == 15 && setflags)
6400 return false;
6401 break;
6402 default:
6403 return false;
6404 }
6405 // Read the register value from the operand register Rn.
6406 uint32_t reg_val = ReadCoreReg(Rn, &success);
6407 if (!success)
6408 return false;
6409
6410 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
6411
6412 EmulateInstruction::Context context;
6413 context.type = EmulateInstruction::eContextImmediate;
6414 context.SetNoArgs ();
6415
6416 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6417 return false;
6418
6419 return true;
6420}
6421
6422// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
6423// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
6424// condition flags based on the result.
6425bool
6426EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
6427{
6428#if 0
6429 // ARM pseudo code...
6430 if ConditionPassed() then
6431 EncodingSpecificOperations();
6432 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6433 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
6434 if d == 15 then
6435 ALUWritePC(result); // setflags is always FALSE here
6436 else
6437 R[d] = result;
6438 if setflags then
6439 APSR.N = result<31>;
6440 APSR.Z = IsZeroBit(result);
6441 APSR.C = carry;
6442 APSR.V = overflow;
6443#endif
6444
6445 bool success = false;
6446 const uint32_t opcode = OpcodeAsUnsigned (&success);
6447 if (!success)
6448 return false;
6449
6450 uint32_t Rd; // the destination register
6451 uint32_t Rn; // the first operand
6452 uint32_t Rm; // the second operand
6453 bool setflags;
6454 ARM_ShifterType shift_t;
6455 uint32_t shift_n; // the shift applied to the value read from Rm
6456 switch (encoding) {
6457 case eEncodingA1:
6458 Rd = Bits32(opcode, 15, 12);
6459 Rn = Bits32(opcode, 19, 16);
6460 Rm = Bits32(opcode, 3, 0);
6461 setflags = BitIsSet(opcode, 20);
6462 shift_n = DecodeImmShiftARM(opcode, shift_t);
6463 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6464 // TODO: Emulate SUBS PC, LR and related instructions.
6465 if (Rd == 15 && setflags)
6466 return false;
6467 break;
6468 default:
6469 return false;
6470 }
6471 // Read the register value from register Rn.
6472 uint32_t val1 = ReadCoreReg(Rn, &success);
6473 if (!success)
6474 return false;
6475
6476 // Read the register value from register Rm.
6477 uint32_t val2 = ReadCoreReg(Rm, &success);
6478 if (!success)
6479 return false;
6480
6481 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6482 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
6483
6484 EmulateInstruction::Context context;
6485 context.type = EmulateInstruction::eContextImmediate;
6486 context.SetNoArgs();
6487 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6488 return false;
6489
6490 return true;
6491}
6492
Johnny Chen9b381772011-02-23 01:01:21 +00006493// Subtract with Carry (immediate) subtracts an immediate value and the value of
6494// NOT (Carry flag) from a register value, and writes the result to the destination register.
6495// It can optionally update the condition flags based on the result.
6496bool
6497EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
6498{
6499#if 0
6500 // ARM pseudo code...
6501 if ConditionPassed() then
6502 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006503 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00006504 if d == 15 then // Can only occur for ARM encoding
6505 ALUWritePC(result); // setflags is always FALSE here
6506 else
6507 R[d] = result;
6508 if setflags then
6509 APSR.N = result<31>;
6510 APSR.Z = IsZeroBit(result);
6511 APSR.C = carry;
6512 APSR.V = overflow;
6513#endif
6514
6515 bool success = false;
6516 const uint32_t opcode = OpcodeAsUnsigned (&success);
6517 if (!success)
6518 return false;
6519
6520 uint32_t Rd; // the destination register
6521 uint32_t Rn; // the first operand
6522 bool setflags;
6523 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6524 switch (encoding) {
6525 case eEncodingT1:
6526 Rd = Bits32(opcode, 11, 8);
6527 Rn = Bits32(opcode, 19, 16);
6528 setflags = BitIsSet(opcode, 20);
6529 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6530 if (BadReg(Rd) || BadReg(Rn))
6531 return false;
6532 break;
6533 case eEncodingA1:
6534 Rd = Bits32(opcode, 15, 12);
6535 Rn = Bits32(opcode, 19, 16);
6536 setflags = BitIsSet(opcode, 20);
6537 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6538 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6539 // TODO: Emulate SUBS PC, LR and related instructions.
6540 if (Rd == 15 && setflags)
6541 return false;
6542 break;
6543 default:
6544 return false;
6545 }
6546 // Read the register value from the operand register Rn.
6547 uint32_t reg_val = ReadCoreReg(Rn, &success);
6548 if (!success)
6549 return false;
6550
6551 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
6552
6553 EmulateInstruction::Context context;
6554 context.type = EmulateInstruction::eContextImmediate;
6555 context.SetNoArgs ();
6556
6557 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6558 return false;
6559
6560 return true;
6561}
6562
6563// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
6564// NOT (Carry flag) from a register value, and writes the result to the destination register.
6565// It can optionally update the condition flags based on the result.
6566bool
6567EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
6568{
6569#if 0
6570 // ARM pseudo code...
6571 if ConditionPassed() then
6572 EncodingSpecificOperations();
6573 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6574 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
6575 if d == 15 then // Can only occur for ARM encoding
6576 ALUWritePC(result); // setflags is always FALSE here
6577 else
6578 R[d] = result;
6579 if setflags then
6580 APSR.N = result<31>;
6581 APSR.Z = IsZeroBit(result);
6582 APSR.C = carry;
6583 APSR.V = overflow;
6584#endif
6585
6586 bool success = false;
6587 const uint32_t opcode = OpcodeAsUnsigned (&success);
6588 if (!success)
6589 return false;
6590
6591 uint32_t Rd; // the destination register
6592 uint32_t Rn; // the first operand
6593 uint32_t Rm; // the second operand
6594 bool setflags;
6595 ARM_ShifterType shift_t;
6596 uint32_t shift_n; // the shift applied to the value read from Rm
6597 switch (encoding) {
6598 case eEncodingT1:
6599 Rd = Rn = Bits32(opcode, 2, 0);
6600 Rm = Bits32(opcode, 5, 3);
6601 setflags = !InITBlock();
6602 shift_t = SRType_LSL;
6603 shift_n = 0;
6604 break;
6605 case eEncodingT2:
6606 Rd = Bits32(opcode, 11, 8);
6607 Rn = Bits32(opcode, 19, 16);
6608 Rm = Bits32(opcode, 3, 0);
6609 setflags = BitIsSet(opcode, 20);
6610 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6611 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6612 return false;
6613 break;
6614 case eEncodingA1:
6615 Rd = Bits32(opcode, 15, 12);
6616 Rn = Bits32(opcode, 19, 16);
6617 Rm = Bits32(opcode, 3, 0);
6618 setflags = BitIsSet(opcode, 20);
6619 shift_n = DecodeImmShiftARM(opcode, shift_t);
6620 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6621 // TODO: Emulate SUBS PC, LR and related instructions.
6622 if (Rd == 15 && setflags)
6623 return false;
6624 break;
6625 default:
6626 return false;
6627 }
6628 // Read the register value from register Rn.
6629 uint32_t val1 = ReadCoreReg(Rn, &success);
6630 if (!success)
6631 return false;
6632
6633 // Read the register value from register Rm.
6634 uint32_t val2 = ReadCoreReg(Rm, &success);
6635 if (!success)
6636 return false;
6637
6638 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6639 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
6640
6641 EmulateInstruction::Context context;
6642 context.type = EmulateInstruction::eContextImmediate;
6643 context.SetNoArgs();
6644 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6645 return false;
6646
6647 return true;
6648}
6649
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006650// This instruction subtracts an immediate value from a register value, and writes the result
6651// to the destination register. It can optionally update the condition flags based on the result.
6652bool
6653EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
6654{
6655#if 0
6656 // ARM pseudo code...
6657 if ConditionPassed() then
6658 EncodingSpecificOperations();
6659 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
6660 R[d] = result;
6661 if setflags then
6662 APSR.N = result<31>;
6663 APSR.Z = IsZeroBit(result);
6664 APSR.C = carry;
6665 APSR.V = overflow;
6666#endif
6667
6668 bool success = false;
6669 const uint32_t opcode = OpcodeAsUnsigned (&success);
6670 if (!success)
6671 return false;
6672
6673 uint32_t Rd; // the destination register
6674 uint32_t Rn; // the first operand
6675 bool setflags;
6676 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
6677 switch (encoding) {
6678 case eEncodingT1:
6679 Rd = Bits32(opcode, 2, 0);
6680 Rn = Bits32(opcode, 5, 3);
6681 setflags = !InITBlock();
6682 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
6683 break;
6684 case eEncodingT2:
6685 Rd = Rn = Bits32(opcode, 10, 8);
6686 setflags = !InITBlock();
6687 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
6688 break;
6689 case eEncodingT3:
6690 Rd = Bits32(opcode, 11, 8);
6691 Rn = Bits32(opcode, 19, 16);
6692 setflags = BitIsSet(opcode, 20);
6693 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6694
6695 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
6696 if (Rd == 15 && setflags)
6697 return EmulateCMPImm(eEncodingT2);
6698
6699 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
6700 if (Rn == 13)
6701 return EmulateSUBSPImm(eEncodingT2);
6702
6703 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
6704 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
6705 return false;
6706 break;
6707 case eEncodingT4:
6708 Rd = Bits32(opcode, 11, 8);
6709 Rn = Bits32(opcode, 19, 16);
6710 setflags = BitIsSet(opcode, 20);
6711 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
6712
6713 // if Rn == '1111' then SEE ADR;
6714 if (Rn == 15)
6715 return EmulateADR(eEncodingT2);
6716
6717 // if Rn == '1101' then SEE SUB (SP minus immediate);
6718 if (Rn == 13)
6719 return EmulateSUBSPImm(eEncodingT3);
6720
6721 if (BadReg(Rd))
6722 return false;
6723 break;
6724 default:
6725 return false;
6726 }
6727 // Read the register value from the operand register Rn.
6728 uint32_t reg_val = ReadCoreReg(Rn, &success);
6729 if (!success)
6730 return false;
6731
6732 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
6733
6734 EmulateInstruction::Context context;
6735 context.type = EmulateInstruction::eContextImmediate;
6736 context.SetNoArgs ();
6737
6738 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6739 return false;
6740
6741 return true;
6742}
6743
6744// This instruction subtracts an immediate value from a register value, and writes the result
6745// to the destination register. It can optionally update the condition flags based on the result.
6746bool
6747EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
6748{
6749#if 0
6750 // ARM pseudo code...
6751 if ConditionPassed() then
6752 EncodingSpecificOperations();
6753 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
6754 if d == 15 then
6755 ALUWritePC(result); // setflags is always FALSE here
6756 else
6757 R[d] = result;
6758 if setflags then
6759 APSR.N = result<31>;
6760 APSR.Z = IsZeroBit(result);
6761 APSR.C = carry;
6762 APSR.V = overflow;
6763#endif
6764
6765 bool success = false;
6766 const uint32_t opcode = OpcodeAsUnsigned (&success);
6767 if (!success)
6768 return false;
6769
6770 uint32_t Rd; // the destination register
6771 uint32_t Rn; // the first operand
6772 bool setflags;
6773 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
6774 switch (encoding) {
6775 case eEncodingA1:
6776 Rd = Bits32(opcode, 15, 12);
6777 Rn = Bits32(opcode, 19, 16);
6778 setflags = BitIsSet(opcode, 20);
6779 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6780
6781 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
6782 if (Rn == 15 && !setflags)
6783 return EmulateADR(eEncodingA2);
6784
6785 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
6786 if (Rn == 13)
6787 return EmulateSUBSPImm(eEncodingA1);
6788
6789 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6790 // TODO: Emulate SUBS PC, LR and related instructions.
6791 if (Rd == 15 && setflags)
6792 return false;
6793 break;
6794 default:
6795 return false;
6796 }
6797 // Read the register value from the operand register Rn.
6798 uint32_t reg_val = ReadCoreReg(Rn, &success);
6799 if (!success)
6800 return false;
6801
6802 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
6803
6804 EmulateInstruction::Context context;
6805 context.type = EmulateInstruction::eContextImmediate;
6806 context.SetNoArgs ();
6807
6808 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6809 return false;
6810
6811 return true;
6812}
6813
Johnny Chen2115b412011-02-21 23:42:44 +00006814// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
6815// immediate value. It updates the condition flags based on the result, and discards the result.
6816bool
6817EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
6818{
6819#if 0
6820 // ARM pseudo code...
6821 if ConditionPassed() then
6822 EncodingSpecificOperations();
6823 result = R[n] EOR imm32;
6824 APSR.N = result<31>;
6825 APSR.Z = IsZeroBit(result);
6826 APSR.C = carry;
6827 // APSR.V unchanged
6828#endif
6829
6830 bool success = false;
6831 const uint32_t opcode = OpcodeAsUnsigned (&success);
6832 if (!success)
6833 return false;
6834
6835 if (ConditionPassed())
6836 {
6837 uint32_t Rn;
6838 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6839 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6840 switch (encoding)
6841 {
6842 case eEncodingT1:
6843 Rn = Bits32(opcode, 19, 16);
6844 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6845 if (BadReg(Rn))
6846 return false;
6847 break;
6848 case eEncodingA1:
6849 Rn = Bits32(opcode, 19, 16);
6850 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6851 break;
6852 default:
6853 return false;
6854 }
6855
6856 // Read the first operand.
6857 uint32_t val1 = ReadCoreReg(Rn, &success);
6858 if (!success)
6859 return false;
6860
6861 uint32_t result = val1 ^ imm32;
6862
6863 EmulateInstruction::Context context;
6864 context.type = EmulateInstruction::eContextImmediate;
6865 context.SetNoArgs ();
6866
6867 if (!WriteFlags(context, result, carry))
6868 return false;
6869 }
6870 return true;
6871}
6872
6873// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
6874// optionally-shifted register value. It updates the condition flags based on the result, and discards
6875// the result.
6876bool
6877EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
6878{
6879#if 0
6880 // ARM pseudo code...
6881 if ConditionPassed() then
6882 EncodingSpecificOperations();
6883 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6884 result = R[n] EOR shifted;
6885 APSR.N = result<31>;
6886 APSR.Z = IsZeroBit(result);
6887 APSR.C = carry;
6888 // APSR.V unchanged
6889#endif
6890
6891 bool success = false;
6892 const uint32_t opcode = OpcodeAsUnsigned (&success);
6893 if (!success)
6894 return false;
6895
6896 if (ConditionPassed())
6897 {
6898 uint32_t Rn, Rm;
6899 ARM_ShifterType shift_t;
6900 uint32_t shift_n; // the shift applied to the value read from Rm
6901 uint32_t carry;
6902 switch (encoding)
6903 {
6904 case eEncodingT1:
6905 Rn = Bits32(opcode, 19, 16);
6906 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006907 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006908 if (BadReg(Rn) || BadReg(Rm))
6909 return false;
6910 break;
6911 case eEncodingA1:
6912 Rn = Bits32(opcode, 19, 16);
6913 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006914 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006915 break;
6916 default:
6917 return false;
6918 }
6919
6920 // Read the first operand.
6921 uint32_t val1 = ReadCoreReg(Rn, &success);
6922 if (!success)
6923 return false;
6924
6925 // Read the second operand.
6926 uint32_t val2 = ReadCoreReg(Rm, &success);
6927 if (!success)
6928 return false;
6929
6930 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6931 uint32_t result = val1 ^ shifted;
6932
6933 EmulateInstruction::Context context;
6934 context.type = EmulateInstruction::eContextImmediate;
6935 context.SetNoArgs ();
6936
6937 if (!WriteFlags(context, result, carry))
6938 return false;
6939 }
6940 return true;
6941}
6942
Johnny Chende3cce32011-02-21 21:24:49 +00006943// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
6944// It updates the condition flags based on the result, and discards the result.
6945bool
6946EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6947{
6948#if 0
6949 // ARM pseudo code...
6950 if ConditionPassed() then
6951 EncodingSpecificOperations();
6952 result = R[n] AND imm32;
6953 APSR.N = result<31>;
6954 APSR.Z = IsZeroBit(result);
6955 APSR.C = carry;
6956 // APSR.V unchanged
6957#endif
6958
6959 bool success = false;
6960 const uint32_t opcode = OpcodeAsUnsigned (&success);
6961 if (!success)
6962 return false;
6963
6964 if (ConditionPassed())
6965 {
6966 uint32_t Rn;
6967 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6968 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6969 switch (encoding)
6970 {
6971 case eEncodingT1:
6972 Rn = Bits32(opcode, 19, 16);
6973 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6974 if (BadReg(Rn))
6975 return false;
6976 break;
6977 case eEncodingA1:
6978 Rn = Bits32(opcode, 19, 16);
6979 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6980 break;
6981 default:
6982 return false;
6983 }
6984
6985 // Read the first operand.
6986 uint32_t val1 = ReadCoreReg(Rn, &success);
6987 if (!success)
6988 return false;
6989
6990 uint32_t result = val1 & imm32;
6991
6992 EmulateInstruction::Context context;
6993 context.type = EmulateInstruction::eContextImmediate;
6994 context.SetNoArgs ();
6995
6996 if (!WriteFlags(context, result, carry))
6997 return false;
6998 }
6999 return true;
7000}
7001
7002// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
7003// It updates the condition flags based on the result, and discards the result.
7004bool
7005EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
7006{
7007#if 0
7008 // ARM pseudo code...
7009 if ConditionPassed() then
7010 EncodingSpecificOperations();
7011 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7012 result = R[n] AND shifted;
7013 APSR.N = result<31>;
7014 APSR.Z = IsZeroBit(result);
7015 APSR.C = carry;
7016 // APSR.V unchanged
7017#endif
7018
7019 bool success = false;
7020 const uint32_t opcode = OpcodeAsUnsigned (&success);
7021 if (!success)
7022 return false;
7023
7024 if (ConditionPassed())
7025 {
7026 uint32_t Rn, Rm;
7027 ARM_ShifterType shift_t;
7028 uint32_t shift_n; // the shift applied to the value read from Rm
7029 uint32_t carry;
7030 switch (encoding)
7031 {
7032 case eEncodingT1:
7033 Rn = Bits32(opcode, 2, 0);
7034 Rm = Bits32(opcode, 5, 3);
7035 shift_t = SRType_LSL;
7036 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007037 break;
Johnny Chende3cce32011-02-21 21:24:49 +00007038 case eEncodingT2:
7039 Rn = Bits32(opcode, 19, 16);
7040 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007041 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00007042 if (BadReg(Rn) || BadReg(Rm))
7043 return false;
7044 break;
7045 case eEncodingA1:
7046 Rn = Bits32(opcode, 19, 16);
7047 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007048 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00007049 break;
7050 default:
7051 return false;
7052 }
7053
7054 // Read the first operand.
7055 uint32_t val1 = ReadCoreReg(Rn, &success);
7056 if (!success)
7057 return false;
7058
7059 // Read the second operand.
7060 uint32_t val2 = ReadCoreReg(Rm, &success);
7061 if (!success)
7062 return false;
7063
7064 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7065 uint32_t result = val1 & shifted;
7066
7067 EmulateInstruction::Context context;
7068 context.type = EmulateInstruction::eContextImmediate;
7069 context.SetNoArgs ();
7070
7071 if (!WriteFlags(context, result, carry))
7072 return false;
7073 }
7074 return true;
7075}
7076
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007077EmulateInstructionARM::ARMOpcode*
7078EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00007079{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007080 static ARMOpcode
7081 g_arm_opcodes[] =
7082 {
7083 //----------------------------------------------------------------------
7084 // Prologue instructions
7085 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00007086
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007087 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00007088 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
7089 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00007090
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007091 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00007092 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00007093 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00007094 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00007095 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
7096 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00007097 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00007098
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007099 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00007100 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00007101
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007102 // push one register
7103 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00007104 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00007105
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007106 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00007107 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
7108 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00007109
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007110 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00007111 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007112 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00007113
Johnny Chen9f687722011-02-18 00:02:28 +00007114 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
7115 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00007116 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007117 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
7118
7119 //----------------------------------------------------------------------
7120 // Supervisor Call (previously Software Interrupt)
7121 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00007122 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
7123
7124 //----------------------------------------------------------------------
7125 // Branch instructions
7126 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007127 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00007128 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
7129 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
7130 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
7131 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00007132 // for example, "bx lr"
7133 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00007134 // bxj
7135 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007136
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007137 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00007138 // Data-processing instructions
7139 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00007140 // adc (immediate)
7141 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
7142 // adc (register)
7143 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00007144 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007145 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00007146 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00007147 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00007148 // adr
7149 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
7150 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007151 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007152 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007153 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00007154 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00007155 // bic (immediate)
7156 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
7157 // bic (register)
7158 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00007159 // eor (immediate)
7160 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
7161 // eor (register)
7162 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007163 // orr (immediate)
7164 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
7165 // orr (register)
7166 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00007167 // rsb (immediate)
7168 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
7169 // rsb (register)
7170 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00007171 // rsc (immediate)
7172 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
7173 // rsc (register)
7174 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00007175 // sbc (immediate)
7176 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
7177 // sbc (register)
7178 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007179 // sub (immediate, ARM)
7180 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007181 // sub (sp minus immediate)
7182 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00007183 // teq (immediate)
7184 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
7185 // teq (register)
7186 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00007187 // tst (immediate)
7188 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
7189 // tst (register)
7190 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
7191
7192
Johnny Chend642a6a2011-02-22 01:01:03 +00007193 // mvn (immediate)
7194 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
7195 // mvn (register)
7196 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00007197 // cmn (immediate)
7198 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
7199 // cmn (register)
7200 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007201 // cmp (immediate)
7202 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
7203 // cmp (register)
7204 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007205 // asr (immediate)
7206 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007207 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00007208 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007209 // lsl (immediate)
7210 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
7211 // lsl (register)
7212 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
7213 // lsr (immediate)
7214 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
7215 // lsr (register)
7216 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007217 // rrx is a special case encoding of ror (immediate)
7218 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
7219 // ror (immediate)
7220 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
7221 // ror (register)
7222 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00007223
7224 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007225 // Load instructions
7226 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00007227 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00007228 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00007229 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00007230 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00007231 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00007232 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00007233 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
7234 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00007235
7236 //----------------------------------------------------------------------
7237 // Store instructions
7238 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00007239 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007240 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00007241 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00007242 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
7243 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00007244
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007245
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007246 };
7247 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
7248
7249 for (size_t i=0; i<k_num_arm_opcodes; ++i)
7250 {
7251 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
7252 return &g_arm_opcodes[i];
7253 }
7254 return NULL;
7255}
Greg Clayton64c84432011-01-21 22:02:52 +00007256
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007257
7258EmulateInstructionARM::ARMOpcode*
7259EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00007260{
Johnny Chenfdd179e2011-01-31 20:09:28 +00007261
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007262 static ARMOpcode
7263 g_thumb_opcodes[] =
7264 {
7265 //----------------------------------------------------------------------
7266 // Prologue instructions
7267 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00007268
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007269 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00007270 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
7271 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
7272 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00007273
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007274 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00007275 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007276 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00007277 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007278 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00007279 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00007280
Johnny Chen864a8e82011-02-18 00:07:39 +00007281 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00007282 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00007283
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007284 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00007285 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007286 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00007287 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
7288 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007289
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007290 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00007291 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
7292 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007293
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007294 //----------------------------------------------------------------------
7295 // Epilogue instructions
7296 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00007297
Johnny Chen864a8e82011-02-18 00:07:39 +00007298 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00007299 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
7300 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
7301 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00007302 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
7303 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007304
7305 //----------------------------------------------------------------------
7306 // Supervisor Call (previously Software Interrupt)
7307 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00007308 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
7309
7310 //----------------------------------------------------------------------
7311 // If Then makes up to four following instructions conditional.
7312 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00007313 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
7314
7315 //----------------------------------------------------------------------
7316 // Branch instructions
7317 //----------------------------------------------------------------------
7318 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
7319 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
7320 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00007321 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007322 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00007323 // J1 == J2 == 1
7324 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
7325 // J1 == J2 == 1
7326 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
7327 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00007328 // for example, "bx lr"
7329 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00007330 // bxj
7331 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00007332 // compare and branch
7333 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00007334 // table branch byte
7335 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
7336 // table branch halfword
7337 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007338
7339 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00007340 // Data-processing instructions
7341 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00007342 // adc (immediate)
7343 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
7344 // adc (register)
7345 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
7346 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
7347 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00007348 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007349 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00007350 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00007351 // adr
7352 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
7353 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
7354 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007355 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007356 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007357 // and (register)
7358 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
7359 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00007360 // bic (immediate)
7361 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
7362 // bic (register)
7363 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
7364 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00007365 // eor (immediate)
7366 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
7367 // eor (register)
7368 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
7369 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007370 // orr (immediate)
7371 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
7372 // orr (register)
7373 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
7374 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00007375 // rsb (immediate)
7376 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
7377 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
7378 // rsb (register)
7379 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00007380 // sbc (immediate)
7381 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
7382 // sbc (register)
7383 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
7384 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007385 // sub (immediate, Thumb)
7386 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
7387 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
7388 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
7389 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007390 // sub (sp minus immediate)
7391 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
7392 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00007393 // teq (immediate)
7394 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
7395 // teq (register)
7396 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00007397 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00007398 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00007399 // tst (register)
7400 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
7401 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
7402
Johnny Chen7c5234d2011-02-18 23:41:11 +00007403
Johnny Chen338bf542011-02-10 19:29:03 +00007404 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00007405 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00007406 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00007407 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007408 // mov{s}<c>.w <Rd>, <Rm>
7409 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00007410 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00007411 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
7412 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00007413 // mvn (immediate)
7414 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
7415 // mvn (register)
7416 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
7417 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007418 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00007419 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007420 // cmn (register)
7421 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007422 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007423 // cmp (immediate)
7424 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007425 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007426 // cmp (register) (Rn and Rm both from r0-r7)
7427 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
7428 // cmp (register) (Rn and Rm not both from r0-r7)
7429 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007430 // asr (immediate)
7431 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00007432 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00007433 // asr (register)
7434 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
7435 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007436 // lsl (immediate)
7437 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
7438 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
7439 // lsl (register)
7440 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
7441 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
7442 // lsr (immediate)
7443 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
7444 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
7445 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00007446 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007447 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007448 // rrx is a special case encoding of ror (immediate)
7449 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
7450 // ror (immediate)
7451 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
7452 // ror (register)
7453 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
7454 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007455
7456 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007457 // Load instructions
7458 //----------------------------------------------------------------------
7459 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00007460 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00007461 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00007462 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
7463 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00007464 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00007465 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
7466 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00007467 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
7468 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
7469 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00007470 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00007471 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
7472 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00007473
7474 //----------------------------------------------------------------------
7475 // Store instructions
7476 //----------------------------------------------------------------------
7477 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007478 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00007479 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00007480 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
7481 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
7482 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
7483 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
7484 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
7485 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
7486 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
7487 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
7488 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007489 };
7490
7491 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
7492 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
7493 {
7494 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
7495 return &g_thumb_opcodes[i];
7496 }
7497 return NULL;
7498}
Greg Clayton64c84432011-01-21 22:02:52 +00007499
Greg Clayton31e2a382011-01-30 20:03:56 +00007500bool
Greg Clayton395fc332011-02-15 21:59:32 +00007501EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00007502{
7503 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00007504 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00007505 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00007506 {
Greg Clayton395fc332011-02-15 21:59:32 +00007507 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
7508 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
7509 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
7510 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
7511 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
7512 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
7513 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
7514 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
7515 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
7516 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00007517 }
7518 return m_arm_isa != 0;
7519}
7520
7521
Greg Clayton64c84432011-01-21 22:02:52 +00007522bool
7523EmulateInstructionARM::ReadInstruction ()
7524{
7525 bool success = false;
7526 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
7527 if (success)
7528 {
7529 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
7530 if (success)
7531 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00007532 Context read_inst_context;
7533 read_inst_context.type = eContextReadOpcode;
7534 read_inst_context.SetNoArgs ();
7535
Greg Clayton64c84432011-01-21 22:02:52 +00007536 if (m_inst_cpsr & MASK_CPSR_T)
7537 {
7538 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007539 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007540
7541 if (success)
7542 {
7543 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
7544 {
7545 m_inst.opcode_type = eOpcode16;
7546 m_inst.opcode.inst16 = thumb_opcode;
7547 }
7548 else
7549 {
7550 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007551 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007552 }
7553 }
7554 }
7555 else
7556 {
7557 m_inst_mode = eModeARM;
7558 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007559 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007560 }
7561 }
7562 }
7563 if (!success)
7564 {
7565 m_inst_mode = eModeInvalid;
7566 m_inst_pc = LLDB_INVALID_ADDRESS;
7567 }
7568 return success;
7569}
7570
Johnny Chenee9b1f72011-02-09 01:00:31 +00007571uint32_t
7572EmulateInstructionARM::ArchVersion ()
7573{
7574 return m_arm_isa;
7575}
7576
Greg Clayton64c84432011-01-21 22:02:52 +00007577bool
7578EmulateInstructionARM::ConditionPassed ()
7579{
7580 if (m_inst_cpsr == 0)
7581 return false;
7582
7583 const uint32_t cond = CurrentCond ();
7584
7585 if (cond == UINT32_MAX)
7586 return false;
7587
7588 bool result = false;
7589 switch (UnsignedBits(cond, 3, 1))
7590 {
7591 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
7592 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
7593 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
7594 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
7595 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
7596 case 5:
7597 {
7598 bool n = (m_inst_cpsr & MASK_CPSR_N);
7599 bool v = (m_inst_cpsr & MASK_CPSR_V);
7600 result = n == v;
7601 }
7602 break;
7603 case 6:
7604 {
7605 bool n = (m_inst_cpsr & MASK_CPSR_N);
7606 bool v = (m_inst_cpsr & MASK_CPSR_V);
7607 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
7608 }
7609 break;
7610 case 7:
7611 result = true;
7612 break;
7613 }
7614
7615 if (cond & 1)
7616 result = !result;
7617 return result;
7618}
7619
Johnny Chen9ee056b2011-02-08 00:06:35 +00007620uint32_t
7621EmulateInstructionARM::CurrentCond ()
7622{
7623 switch (m_inst_mode)
7624 {
7625 default:
7626 case eModeInvalid:
7627 break;
7628
7629 case eModeARM:
7630 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
7631
7632 case eModeThumb:
7633 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
7634 // 'cond' field of the encoding.
7635 if (m_inst.opcode_type == eOpcode16 &&
7636 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
7637 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
7638 {
7639 return Bits32(m_inst.opcode.inst16, 11, 7);
7640 }
7641 else if (m_inst.opcode_type == eOpcode32 &&
7642 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
7643 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
7644 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
7645 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
7646 {
7647 return Bits32(m_inst.opcode.inst32, 25, 22);
7648 }
7649
7650 return m_it_session.GetCond();
7651 }
7652 return UINT32_MAX; // Return invalid value
7653}
7654
Johnny Chen9ee056b2011-02-08 00:06:35 +00007655bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00007656EmulateInstructionARM::InITBlock()
7657{
7658 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
7659}
7660
7661bool
7662EmulateInstructionARM::LastInITBlock()
7663{
7664 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
7665}
7666
7667bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00007668EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
7669{
7670 addr_t target;
7671
Johnny Chenee9b1f72011-02-09 01:00:31 +00007672 // Check the current instruction set.
7673 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007674 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007675 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00007676 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007677
Johnny Chen9ee056b2011-02-08 00:06:35 +00007678 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007679 return false;
7680
7681 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007682}
7683
7684// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
7685bool
Johnny Chen668b4512011-02-15 21:08:58 +00007686EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007687{
7688 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00007689 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
7690 // we want to record it and issue a WriteRegister callback so the clients
7691 // can track the mode changes accordingly.
7692 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007693
7694 if (BitIsSet(addr, 0))
7695 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007696 if (CurrentInstrSet() != eModeThumb)
7697 {
7698 SelectInstrSet(eModeThumb);
7699 cpsr_changed = true;
7700 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007701 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00007702 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007703 }
7704 else if (BitIsClear(addr, 1))
7705 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007706 if (CurrentInstrSet() != eModeARM)
7707 {
7708 SelectInstrSet(eModeARM);
7709 cpsr_changed = true;
7710 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007711 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00007712 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007713 }
7714 else
7715 return false; // address<1:0> == '10' => UNPREDICTABLE
7716
Johnny Chen0f309db2011-02-09 19:11:32 +00007717 if (cpsr_changed)
7718 {
Johnny Chen558133b2011-02-09 23:59:17 +00007719 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00007720 return false;
7721 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007722 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007723 return false;
7724
7725 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007726}
Greg Clayton64c84432011-01-21 22:02:52 +00007727
Johnny Chenee9b1f72011-02-09 01:00:31 +00007728// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
7729bool
Johnny Chen668b4512011-02-15 21:08:58 +00007730EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00007731{
7732 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00007733 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00007734 else
7735 return BranchWritePC((const Context)context, addr);
7736}
7737
Johnny Chen26863dc2011-02-09 23:43:29 +00007738// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
7739bool
Johnny Chen668b4512011-02-15 21:08:58 +00007740EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00007741{
7742 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00007743 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00007744 else
7745 return BranchWritePC((const Context)context, addr);
7746}
7747
Johnny Chenee9b1f72011-02-09 01:00:31 +00007748EmulateInstructionARM::Mode
7749EmulateInstructionARM::CurrentInstrSet ()
7750{
7751 return m_inst_mode;
7752}
7753
7754// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00007755// ReadInstruction() is performed. This function has a side effect of updating
7756// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00007757bool
7758EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
7759{
Johnny Chen558133b2011-02-09 23:59:17 +00007760 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007761 switch (arm_or_thumb)
7762 {
7763 default:
7764 return false;
7765 eModeARM:
7766 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007767 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007768 break;
7769 eModeThumb:
7770 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007771 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007772 break;
7773 }
7774 return true;
7775}
7776
Johnny Chenef21b592011-02-10 01:52:38 +00007777// This function returns TRUE if the processor currently provides support for
7778// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
7779// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
7780bool
7781EmulateInstructionARM::UnalignedSupport()
7782{
7783 return (ArchVersion() >= ARMv7);
7784}
7785
Johnny Chenbf6ad172011-02-11 01:29:53 +00007786// The main addition and subtraction instructions can produce status information
7787// about both unsigned carry and signed overflow conditions. This status
7788// information can be used to synthesize multi-word additions and subtractions.
7789EmulateInstructionARM::AddWithCarryResult
7790EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
7791{
7792 uint32_t result;
7793 uint8_t carry_out;
7794 uint8_t overflow;
7795
7796 uint64_t unsigned_sum = x + y + carry_in;
7797 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
7798
7799 result = UnsignedBits(unsigned_sum, 31, 0);
7800 carry_out = (result == unsigned_sum ? 0 : 1);
7801 overflow = ((int32_t)result == signed_sum ? 0 : 1);
7802
7803 AddWithCarryResult res = { result, carry_out, overflow };
7804 return res;
7805}
7806
Johnny Chen157b9592011-02-18 21:13:05 +00007807uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00007808EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00007809{
Johnny Chene39f22d2011-02-19 01:36:13 +00007810 uint32_t reg_kind, reg_num;
7811 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00007812 {
Johnny Chene39f22d2011-02-19 01:36:13 +00007813 case SP_REG:
7814 reg_kind = eRegisterKindGeneric;
7815 reg_num = LLDB_REGNUM_GENERIC_SP;
7816 break;
7817 case LR_REG:
7818 reg_kind = eRegisterKindGeneric;
7819 reg_num = LLDB_REGNUM_GENERIC_RA;
7820 break;
7821 case PC_REG:
7822 reg_kind = eRegisterKindGeneric;
7823 reg_num = LLDB_REGNUM_GENERIC_PC;
7824 break;
7825 default:
7826 if (0 <= num && num < SP_REG)
7827 {
7828 reg_kind = eRegisterKindDWARF;
7829 reg_num = dwarf_r0 + num;
7830 }
Johnny Chen157b9592011-02-18 21:13:05 +00007831 else
Johnny Chene39f22d2011-02-19 01:36:13 +00007832 {
7833 assert(0 && "Invalid register number");
7834 *success = false;
7835 return ~0u;
7836 }
7837 break;
Johnny Chen157b9592011-02-18 21:13:05 +00007838 }
Johnny Chene39f22d2011-02-19 01:36:13 +00007839
7840 // Read our register.
7841 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
7842
7843 // When executing an ARM instruction , PC reads as the address of the current
7844 // instruction plus 8.
7845 // When executing a Thumb instruction , PC reads as the address of the current
7846 // instruction plus 4.
7847 if (num == 15)
7848 {
7849 if (CurrentInstrSet() == eModeARM)
7850 val += 8;
7851 else
7852 val += 4;
7853 }
Johnny Chen157b9592011-02-18 21:13:05 +00007854
7855 return val;
7856}
7857
Johnny Chenca67d1c2011-02-17 01:35:27 +00007858// Write the result to the ARM core register Rd, and optionally update the
7859// condition flags based on the result.
7860//
7861// This helper method tries to encapsulate the following pseudocode from the
7862// ARM Architecture Reference Manual:
7863//
7864// if d == 15 then // Can only occur for encoding A1
7865// ALUWritePC(result); // setflags is always FALSE here
7866// else
7867// R[d] = result;
7868// if setflags then
7869// APSR.N = result<31>;
7870// APSR.Z = IsZeroBit(result);
7871// APSR.C = carry;
7872// // APSR.V unchanged
7873//
7874// In the above case, the API client does not pass in the overflow arg, which
7875// defaults to ~0u.
7876bool
Johnny Chen10530c22011-02-17 22:37:12 +00007877EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
7878 const uint32_t result,
7879 const uint32_t Rd,
7880 bool setflags,
7881 const uint32_t carry,
7882 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00007883{
7884 if (Rd == 15)
7885 {
7886 if (!ALUWritePC (context, result))
7887 return false;
7888 }
7889 else
7890 {
Johnny Chena695f952011-02-23 21:24:25 +00007891 uint32_t reg_kind, reg_num;
7892 switch (Rd)
7893 {
7894 case SP_REG:
7895 reg_kind = eRegisterKindGeneric;
7896 reg_num = LLDB_REGNUM_GENERIC_SP;
7897 break;
7898 case LR_REG:
7899 reg_kind = eRegisterKindGeneric;
7900 reg_num = LLDB_REGNUM_GENERIC_RA;
7901 break;
7902 default:
7903 reg_kind = eRegisterKindDWARF;
7904 reg_num = dwarf_r0 + Rd;
7905 }
7906 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00007907 return false;
7908 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00007909 return WriteFlags (context, result, carry, overflow);
7910 }
7911 return true;
7912}
7913
7914// This helper method tries to encapsulate the following pseudocode from the
7915// ARM Architecture Reference Manual:
7916//
7917// APSR.N = result<31>;
7918// APSR.Z = IsZeroBit(result);
7919// APSR.C = carry;
7920// APSR.V = overflow
7921//
7922// Default arguments can be specified for carry and overflow parameters, which means
7923// not to update the respective flags.
7924bool
7925EmulateInstructionARM::WriteFlags (Context &context,
7926 const uint32_t result,
7927 const uint32_t carry,
7928 const uint32_t overflow)
7929{
7930 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00007931 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
7932 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00007933 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007934 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00007935 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007936 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00007937 if (m_new_inst_cpsr != m_inst_cpsr)
7938 {
7939 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
7940 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00007941 }
7942 return true;
7943}
7944
Greg Clayton64c84432011-01-21 22:02:52 +00007945bool
7946EmulateInstructionARM::EvaluateInstruction ()
7947{
Johnny Chenc315f862011-02-05 00:46:10 +00007948 // Advance the ITSTATE bits to their values for the next instruction.
7949 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
7950 m_it_session.ITAdvance();
7951
Greg Clayton64c84432011-01-21 22:02:52 +00007952 return false;
7953}