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