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