blob: 00f456c613c39c9ddc9887da12d99ddd19cbc98c [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)
132#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000133
Johnny Chen0e00af22011-02-10 19:40:42 +0000134//----------------------------------------------------------------------
135//
136// EmulateInstructionARM implementation
137//
138//----------------------------------------------------------------------
139
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140void
141EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145void
146EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000147{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000148}
149
Caroline Ticefa172202011-02-11 22:49:54 +0000150// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
151bool
152EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
153{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000154 EmulateInstruction::Context context;
155 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
156 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000157
158 uint32_t random_data = rand ();
159 const uint32_t addr_byte_size = GetAddressByteSize();
160
Caroline Ticecc96eb52011-02-17 19:20:40 +0000161 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000162 return false;
163
164 return true;
165}
166
Caroline Tice713c2662011-02-11 17:59:55 +0000167// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
168bool
169EmulateInstructionARM::WriteBits32Unknown (int n)
170{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000171 EmulateInstruction::Context context;
172 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
173 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000174
Johnny Chen62ff6f52011-02-11 18:11:22 +0000175 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
177
178 if (!success)
179 return false;
180
181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
182 return false;
183
184 return true;
185}
186
Johnny Chen08c25e82011-01-31 18:02:28 +0000187// Push Multiple Registers stores multiple registers to the stack, storing to
188// consecutive memory locations ending just below the address in SP, and updates
189// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000190bool
Johnny Chen9f687722011-02-18 00:02:28 +0000191EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000192{
193#if 0
194 // ARM pseudo code...
195 if (ConditionPassed())
196 {
197 EncodingSpecificOperations();
198 NullCheckIfThumbEE(13);
199 address = SP - 4*BitCount(registers);
200
201 for (i = 0 to 14)
202 {
203 if (registers<i> == ’1’)
204 {
205 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
206 MemA[address,4] = bits(32) UNKNOWN;
207 else
208 MemA[address,4] = R[i];
209 address = address + 4;
210 }
211 }
212
213 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
214 MemA[address,4] = PCStoreValue();
215
216 SP = SP - 4*BitCount(registers);
217 }
218#endif
219
220 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000222 if (!success)
223 return false;
224
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000228 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000232 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000235 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000237 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000238 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000239 // if BitCount(registers) < 1 then UNPREDICTABLE;
240 if (BitCount(registers) < 1)
241 return false;
242 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 case eEncodingT2:
244 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000245 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000246 // if BitCount(registers) < 2 then UNPREDICTABLE;
247 if (BitCount(registers) < 2)
248 return false;
249 break;
250 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000251 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000257 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000258 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000259 // Instead of return false, let's handle the following case as well,
260 // which amounts to pushing one reg onto the full descending stacks.
261 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000262 break;
263 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000264 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000265 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000270 default:
271 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000272 }
Johnny Chence1ca772011-01-25 01:13:00 +0000273 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000274 addr_t addr = sp - sp_offset;
275 uint32_t i;
276
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000277 EmulateInstruction::Context context;
278 context.type = EmulateInstruction::eContextPushRegisterOnStack;
279 Register dwarf_reg;
280 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000281 for (i=0; i<15; ++i)
282 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000283 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000285 dwarf_reg.num = dwarf_r0 + i;
286 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000290 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000291 return false;
292 addr += addr_byte_size;
293 }
294 }
295
Johnny Chen7c1bf922011-02-08 23:49:37 +0000296 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000297 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000298 dwarf_reg.num = dwarf_pc;
299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000300 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000301 if (!success)
302 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000303 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000304 return false;
305 }
306
307 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000308 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000309
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000311 return false;
312 }
313 return true;
314}
315
Johnny Chenef85e912011-01-31 23:07:40 +0000316// Pop Multiple Registers loads multiple registers from the stack, loading from
317// consecutive memory locations staring at the address in SP, and updates
318// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319bool
Johnny Chen9f687722011-02-18 00:02:28 +0000320EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000321{
322#if 0
323 // ARM pseudo code...
324 if (ConditionPassed())
325 {
326 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
327 address = SP;
328 for i = 0 to 14
329 if registers<i> == ‘1’ then
330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
331 if registers<15> == ‘1’ then
332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
336 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
337 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
338 }
339#endif
340
341 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000343 if (!success)
344 return false;
345
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000347 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000349 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000350 if (!success)
351 return false;
352 uint32_t registers = 0;
353 uint32_t Rt; // the destination register
354 switch (encoding) {
355 case eEncodingT1:
356 registers = Bits32(opcode, 7, 0);
357 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000358 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000359 registers |= (1u << 15);
360 // if BitCount(registers) < 1 then UNPREDICTABLE;
361 if (BitCount(registers) < 1)
362 return false;
363 break;
364 case eEncodingT2:
365 // Ignore bit 13.
366 registers = Bits32(opcode, 15, 0) & ~0x2000;
367 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000368 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000370 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
371 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
372 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000373 break;
374 case eEncodingT3:
375 Rt = Bits32(opcode, 15, 12);
376 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000377 if (Rt == 13)
378 return false;
379 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000380 return false;
381 registers = (1u << Rt);
382 break;
383 case eEncodingA1:
384 registers = Bits32(opcode, 15, 0);
385 // Instead of return false, let's handle the following case as well,
386 // which amounts to popping one reg from the full descending stacks.
387 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
388
389 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000390 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000391 return false;
392 break;
393 case eEncodingA2:
394 Rt = Bits32(opcode, 15, 12);
395 // if t == 13 then UNPREDICTABLE;
396 if (Rt == dwarf_sp)
397 return false;
398 registers = (1u << Rt);
399 break;
400 default:
401 return false;
402 }
403 addr_t sp_offset = addr_byte_size * BitCount (registers);
404 addr_t addr = sp;
405 uint32_t i, data;
406
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000407 EmulateInstruction::Context context;
408 context.type = EmulateInstruction::eContextPopRegisterOffStack;
409 Register dwarf_reg;
410 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000411 for (i=0; i<15; ++i)
412 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000413 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 dwarf_reg.num = dwarf_r0 + i;
416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000417 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000418 if (!success)
419 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 return false;
422 addr += addr_byte_size;
423 }
424 }
425
Johnny Chen7c1bf922011-02-08 23:49:37 +0000426 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000428 dwarf_reg.num = dwarf_pc;
429 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000430 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000431 if (!success)
432 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000433 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000434 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 addr += addr_byte_size;
437 }
438
439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000440 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000441
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 }
445 return true;
446}
447
Johnny Chen5b442b72011-01-27 19:34:30 +0000448// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000450bool
Johnny Chen9f687722011-02-18 00:02:28 +0000451EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000452{
453#if 0
454 // ARM pseudo code...
455 if (ConditionPassed())
456 {
457 EncodingSpecificOperations();
458 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
459 if d == 15 then
460 ALUWritePC(result); // setflags is always FALSE here
461 else
462 R[d] = result;
463 if setflags then
464 APSR.N = result<31>;
465 APSR.Z = IsZeroBit(result);
466 APSR.C = carry;
467 APSR.V = overflow;
468 }
469#endif
470
471 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 if (!success)
474 return false;
475
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000478 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481 uint32_t Rd; // the destination register
482 uint32_t imm32;
483 switch (encoding) {
484 case eEncodingT1:
485 Rd = 7;
486 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
487 break;
488 case eEncodingA1:
489 Rd = Bits32(opcode, 15, 12);
490 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
491 break;
492 default:
493 return false;
494 }
495 addr_t sp_offset = imm32;
496 addr_t addr = sp + sp_offset; // a pointer to the stack area
497
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000498 EmulateInstruction::Context context;
499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
500 Register sp_reg;
501 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
502 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000505 return false;
506 }
507 return true;
508}
509
Johnny Chen2ccad832011-01-28 19:57:25 +0000510// Set r7 or ip to the current stack pointer.
511// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000512bool
Johnny Chen9f687722011-02-18 00:02:28 +0000513EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000514{
515#if 0
516 // ARM pseudo code...
517 if (ConditionPassed())
518 {
519 EncodingSpecificOperations();
520 result = R[m];
521 if d == 15 then
522 ALUWritePC(result); // setflags is always FALSE here
523 else
524 R[d] = result;
525 if setflags then
526 APSR.N = result<31>;
527 APSR.Z = IsZeroBit(result);
528 // APSR.C unchanged
529 // APSR.V unchanged
530 }
531#endif
532
533 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000535 //if (!success)
536 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000537
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000540 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000541 if (!success)
542 return false;
543 uint32_t Rd; // the destination register
544 switch (encoding) {
545 case eEncodingT1:
546 Rd = 7;
547 break;
548 case eEncodingA1:
549 Rd = 12;
550 break;
551 default:
552 return false;
553 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000554
555 EmulateInstruction::Context context;
556 context.type = EmulateInstruction::eContextRegisterPlusOffset;
557 Register sp_reg;
558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
559 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000560
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000562 return false;
563 }
564 return true;
565}
566
Johnny Chen1c13b622011-01-29 00:11:15 +0000567// Move from high register (r8-r15) to low register (r0-r7).
568// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569bool
Johnny Chen9f687722011-02-18 00:02:28 +0000570EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000571{
Johnny Chen9f687722011-02-18 00:02:28 +0000572 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000573}
574
575// Move from register to register.
576// MOV (register)
577bool
Johnny Chen9f687722011-02-18 00:02:28 +0000578EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000579{
Johnny Chen1c13b622011-01-29 00:11:15 +0000580#if 0
581 // ARM pseudo code...
582 if (ConditionPassed())
583 {
584 EncodingSpecificOperations();
585 result = R[m];
586 if d == 15 then
587 ALUWritePC(result); // setflags is always FALSE here
588 else
589 R[d] = result;
590 if setflags then
591 APSR.N = result<31>;
592 APSR.Z = IsZeroBit(result);
593 // APSR.C unchanged
594 // APSR.V unchanged
595 }
596#endif
597
598 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 if (!success)
601 return false;
602
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000603 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 {
605 uint32_t Rm; // the source register
606 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000607 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000608 switch (encoding) {
609 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000610 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000612 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000613 if (Rd == 15 && InITBlock() && !LastInITBlock())
614 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000615 break;
616 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000617 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000620 if (InITBlock())
621 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000622 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 case eEncodingT3:
624 Rd = Bits32(opcode, 11, 8);
625 Rm = Bits32(opcode, 3, 0);
626 setflags = BitIsSet(opcode, 20);
627 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
628 if (setflags && (BadReg(Rd) || BadReg(Rm)))
629 return false;
630 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
631 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
632 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000633 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000634 default:
635 return false;
636 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000637 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000638 if (!success)
639 return false;
640
641 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000642 EmulateInstruction::Context context;
643 context.type = EmulateInstruction::eContextRegisterPlusOffset;
644 Register dwarf_reg;
645 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
646 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000647
Johnny Chen10530c22011-02-17 22:37:12 +0000648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000649 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
Johnny Chen9f687722011-02-18 00:02:28 +0000658EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
677 bool success = false;
678 const uint32_t opcode = OpcodeAsUnsigned (&success);
679 if (!success)
680 return false;
681
682 if (ConditionPassed())
683 {
684 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000685 uint32_t imm32; // the immediate value to be written to Rd
686 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
687 bool setflags;
688 switch (encoding) {
689 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000690 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000691 setflags = !InITBlock();
692 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000693 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000694 break;
695 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000696 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000697 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000698 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000699 if (BadReg(Rd))
700 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000701 break;
702 default:
703 return false;
704 }
705 uint32_t result = imm32;
706
707 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000708 EmulateInstruction::Context context;
709 context.type = EmulateInstruction::eContextImmediate;
710 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000711
Johnny Chen10530c22011-02-17 22:37:12 +0000712 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000713 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000714 }
715 return true;
716}
717
Johnny Chend642a6a2011-02-22 01:01:03 +0000718// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
719// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000720bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000721EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000722{
723#if 0
724 // ARM pseudo code...
725 if (ConditionPassed())
726 {
727 EncodingSpecificOperations();
728 result = NOT(imm32);
729 if d == 15 then // Can only occur for ARM encoding
730 ALUWritePC(result); // setflags is always FALSE here
731 else
732 R[d] = result;
733 if setflags then
734 APSR.N = result<31>;
735 APSR.Z = IsZeroBit(result);
736 APSR.C = carry;
737 // APSR.V unchanged
738 }
739#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000740 bool success = false;
741 const uint32_t opcode = OpcodeAsUnsigned (&success);
742 if (!success)
743 return false;
744
745 if (ConditionPassed())
746 {
747 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000748 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
749 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000750 bool setflags;
751 switch (encoding) {
752 case eEncodingT1:
753 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000754 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000755 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000756 break;
757 case eEncodingA1:
758 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000759 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000760 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
761 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
762 // TODO: Emulate SUBS PC, LR and related instructions.
763 if (Rd == 15 && setflags)
764 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 break;
766 default:
767 return false;
768 }
769 uint32_t result = ~imm32;
770
771 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000772 EmulateInstruction::Context context;
773 context.type = EmulateInstruction::eContextImmediate;
774 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000775
Johnny Chen10530c22011-02-17 22:37:12 +0000776 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000777 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000778 }
779 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000780}
781
Johnny Chend642a6a2011-02-22 01:01:03 +0000782// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
783// It can optionally update the condition flags based on the result.
784bool
785EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
786{
787#if 0
788 // ARM pseudo code...
789 if (ConditionPassed())
790 {
791 EncodingSpecificOperations();
792 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
793 result = NOT(shifted);
794 if d == 15 then // Can only occur for ARM encoding
795 ALUWritePC(result); // setflags is always FALSE here
796 else
797 R[d] = result;
798 if setflags then
799 APSR.N = result<31>;
800 APSR.Z = IsZeroBit(result);
801 APSR.C = carry;
802 // APSR.V unchanged
803 }
804#endif
805
806 bool success = false;
807 const uint32_t opcode = OpcodeAsUnsigned (&success);
808 if (!success)
809 return false;
810
811 if (ConditionPassed())
812 {
813 uint32_t Rm; // the source register
814 uint32_t Rd; // the destination register
815 ARM_ShifterType shift_t;
816 uint32_t shift_n; // the shift applied to the value read from Rm
817 bool setflags;
818 uint32_t carry; // the carry bit after the shift operation
819 switch (encoding) {
820 case eEncodingT1:
821 Rd = Bits32(opcode, 2, 0);
822 Rm = Bits32(opcode, 5, 3);
823 setflags = !InITBlock();
824 shift_t = SRType_LSL;
825 shift_n = 0;
826 if (InITBlock())
827 return false;
828 break;
829 case eEncodingT2:
830 Rd = Bits32(opcode, 11, 8);
831 Rm = Bits32(opcode, 3, 0);
832 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000833 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000834 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000835 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000836 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000837 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000838 case eEncodingA1:
839 Rd = Bits32(opcode, 15, 12);
840 Rm = Bits32(opcode, 3, 0);
841 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000842 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000843 break;
844 default:
845 return false;
846 }
847 uint32_t value = ReadCoreReg(Rm, &success);
848 if (!success)
849 return false;
850
851 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
852 uint32_t result = ~shifted;
853
854 // The context specifies that an immediate is to be moved into Rd.
855 EmulateInstruction::Context context;
856 context.type = EmulateInstruction::eContextImmediate;
857 context.SetNoArgs ();
858
859 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
860 return false;
861 }
862 return true;
863}
864
Johnny Chen788e0552011-01-27 22:52:23 +0000865// PC relative immediate load into register, possibly followed by ADD (SP plus register).
866// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000867bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000868EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000869{
870#if 0
871 // ARM pseudo code...
872 if (ConditionPassed())
873 {
874 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
875 base = Align(PC,4);
876 address = if add then (base + imm32) else (base - imm32);
877 data = MemU[address,4];
878 if t == 15 then
879 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
880 elsif UnalignedSupport() || address<1:0> = ‘00’ then
881 R[t] = data;
882 else // Can only apply before ARMv7
883 if CurrentInstrSet() == InstrSet_ARM then
884 R[t] = ROR(data, 8*UInt(address<1:0>));
885 else
886 R[t] = bits(32) UNKNOWN;
887 }
888#endif
889
890 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000891 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000892 if (!success)
893 return false;
894
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000895 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000896 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000897 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000898 if (!success)
899 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000900
901 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000902 EmulateInstruction::Context context;
903 context.type = EmulateInstruction::eContextRegisterPlusOffset;
904 Register pc_reg;
905 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
906 context.SetRegisterPlusOffset (pc_reg, 0);
907
Johnny Chenc9de9102011-02-11 19:12:30 +0000908 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000909 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000910 bool add; // +imm32 or -imm32?
911 addr_t base; // the base address
912 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000913 uint32_t data; // the literal data value from the PC relative load
914 switch (encoding) {
915 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000916 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000917 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000918 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000919 break;
920 case eEncodingT2:
921 Rt = Bits32(opcode, 15, 12);
922 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
923 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000924 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000925 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000926 break;
927 default:
928 return false;
929 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000930
Johnny Chene39f22d2011-02-19 01:36:13 +0000931 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000932 if (add)
933 address = base + imm32;
934 else
935 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000936
937 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000938 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000939 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000940 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000941
942 if (Rt == 15)
943 {
944 if (Bits32(address, 1, 0) == 0)
945 {
946 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000947 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000948 return false;
949 }
950 else
951 return false;
952 }
953 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
954 {
955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
956 return false;
957 }
958 else // We don't handle ARM for now.
959 return false;
960
961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000962 return false;
963 }
964 return true;
965}
966
Johnny Chen5b442b72011-01-27 19:34:30 +0000967// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000968// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000969bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000970EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000971{
972#if 0
973 // ARM pseudo code...
974 if (ConditionPassed())
975 {
976 EncodingSpecificOperations();
977 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
978 if d == 15 then // Can only occur for ARM encoding
979 ALUWritePC(result); // setflags is always FALSE here
980 else
981 R[d] = result;
982 if setflags then
983 APSR.N = result<31>;
984 APSR.Z = IsZeroBit(result);
985 APSR.C = carry;
986 APSR.V = overflow;
987 }
988#endif
989
990 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000991 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000992 if (!success)
993 return false;
994
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000995 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000996 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000997 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000998 if (!success)
999 return false;
1000 uint32_t imm32; // the immediate operand
1001 switch (encoding) {
1002 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001003 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001004 break;
1005 default:
1006 return false;
1007 }
1008 addr_t sp_offset = imm32;
1009 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1010
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001011 EmulateInstruction::Context context;
1012 context.type = EmulateInstruction::eContextAdjustStackPointer;
1013 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001014
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001015 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001016 return false;
1017 }
1018 return true;
1019}
1020
1021// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001022// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001023bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001024EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001025{
1026#if 0
1027 // ARM pseudo code...
1028 if (ConditionPassed())
1029 {
1030 EncodingSpecificOperations();
1031 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1032 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1033 if d == 15 then
1034 ALUWritePC(result); // setflags is always FALSE here
1035 else
1036 R[d] = result;
1037 if setflags then
1038 APSR.N = result<31>;
1039 APSR.Z = IsZeroBit(result);
1040 APSR.C = carry;
1041 APSR.V = overflow;
1042 }
1043#endif
1044
1045 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001046 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001047 if (!success)
1048 return false;
1049
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001050 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001051 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001052 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001053 if (!success)
1054 return false;
1055 uint32_t Rm; // the second operand
1056 switch (encoding) {
1057 case eEncodingT2:
1058 Rm = Bits32(opcode, 6, 3);
1059 break;
1060 default:
1061 return false;
1062 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001063 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001064 if (!success)
1065 return false;
1066
1067 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1068
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001069 EmulateInstruction::Context context;
1070 context.type = EmulateInstruction::eContextAdjustStackPointer;
1071 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001072
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001073 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001074 return false;
1075 }
1076 return true;
1077}
1078
Johnny Chen9b8d7832011-02-02 01:13:56 +00001079// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1080// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1081// from Thumb to ARM.
1082// BLX (immediate)
1083bool
1084EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1085{
1086#if 0
1087 // ARM pseudo code...
1088 if (ConditionPassed())
1089 {
1090 EncodingSpecificOperations();
1091 if CurrentInstrSet() == InstrSet_ARM then
1092 LR = PC - 4;
1093 else
1094 LR = PC<31:1> : '1';
1095 if targetInstrSet == InstrSet_ARM then
1096 targetAddress = Align(PC,4) + imm32;
1097 else
1098 targetAddress = PC + imm32;
1099 SelectInstrSet(targetInstrSet);
1100 BranchWritePC(targetAddress);
1101 }
1102#endif
1103
1104 bool success = false;
1105 const uint32_t opcode = OpcodeAsUnsigned (&success);
1106 if (!success)
1107 return false;
1108
1109 if (ConditionPassed())
1110 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001111 EmulateInstruction::Context context;
1112 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001113 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 if (!success)
1115 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001116 addr_t lr; // next instruction address
1117 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001118 int32_t imm32; // PC-relative offset
1119 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001120 case eEncodingT1:
1121 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001122 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001123 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001124 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001125 uint32_t J1 = Bit32(opcode, 13);
1126 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001127 uint32_t imm11 = Bits32(opcode, 10, 0);
1128 uint32_t I1 = !(J1 ^ S);
1129 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001130 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001131 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001132 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001133 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001134 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001135 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001136 break;
1137 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001138 case eEncodingT2:
1139 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001140 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001141 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001142 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001143 uint32_t J1 = Bit32(opcode, 13);
1144 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001145 uint32_t imm10L = Bits32(opcode, 10, 1);
1146 uint32_t I1 = !(J1 ^ S);
1147 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001148 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001149 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001150 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001151 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001152 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001153 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001154 break;
1155 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001156 case eEncodingA1:
1157 lr = pc + 4; // return address
1158 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001159 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001160 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001161 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001162 case eEncodingA2:
1163 lr = pc + 4; // return address
1164 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001165 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001166 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001167 break;
1168 default:
1169 return false;
1170 }
1171 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1172 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001173 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001174 return false;
1175 }
1176 return true;
1177}
1178
1179// Branch with Link and Exchange (register) calls a subroutine at an address and
1180// instruction set specified by a register.
1181// BLX (register)
1182bool
1183EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1184{
1185#if 0
1186 // ARM pseudo code...
1187 if (ConditionPassed())
1188 {
1189 EncodingSpecificOperations();
1190 target = R[m];
1191 if CurrentInstrSet() == InstrSet_ARM then
1192 next_instr_addr = PC - 4;
1193 LR = next_instr_addr;
1194 else
1195 next_instr_addr = PC - 2;
1196 LR = next_instr_addr<31:1> : ‘1’;
1197 BXWritePC(target);
1198 }
1199#endif
1200
1201 bool success = false;
1202 const uint32_t opcode = OpcodeAsUnsigned (&success);
1203 if (!success)
1204 return false;
1205
1206 if (ConditionPassed())
1207 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001208 EmulateInstruction::Context context;
1209 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001210 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001211 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001212 if (!success)
1213 return false;
1214 uint32_t Rm; // the register with the target address
1215 switch (encoding) {
1216 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001217 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001218 Rm = Bits32(opcode, 6, 3);
1219 // if m == 15 then UNPREDICTABLE;
1220 if (Rm == 15)
1221 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001222 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001223 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001224 break;
1225 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001226 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001227 Rm = Bits32(opcode, 3, 0);
1228 // if m == 15 then UNPREDICTABLE;
1229 if (Rm == 15)
1230 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001231 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001232 default:
1233 return false;
1234 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001235 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001236 if (!success)
1237 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001238 Register dwarf_reg;
1239 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1240 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001241 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1242 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001243 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001244 return false;
1245 }
1246 return true;
1247}
1248
Johnny Chenab3b3512011-02-12 00:10:51 +00001249// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1250// BX
1251bool
1252EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1253{
1254#if 0
1255 // ARM pseudo code...
1256 if (ConditionPassed())
1257 {
1258 EncodingSpecificOperations();
1259 BXWritePC(R[m]);
1260 }
1261#endif
1262
1263 bool success = false;
1264 const uint32_t opcode = OpcodeAsUnsigned (&success);
1265 if (!success)
1266 return false;
1267
1268 if (ConditionPassed())
1269 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001270 EmulateInstruction::Context context;
1271 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001272 uint32_t Rm; // the register with the target address
1273 switch (encoding) {
1274 case eEncodingT1:
1275 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001276 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001277 return false;
1278 break;
1279 case eEncodingA1:
1280 Rm = Bits32(opcode, 3, 0);
1281 break;
1282 default:
1283 return false;
1284 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001285 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001286 if (!success)
1287 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001288
1289 Register dwarf_reg;
1290 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001291 context.SetRegister (dwarf_reg);
1292 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001293 return false;
1294 }
1295 return true;
1296}
1297
Johnny Chen0d0148e2011-01-28 02:26:08 +00001298// Set r7 to point to some ip offset.
1299// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001300bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001301EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001302{
1303#if 0
1304 // ARM pseudo code...
1305 if (ConditionPassed())
1306 {
1307 EncodingSpecificOperations();
1308 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1309 if d == 15 then // Can only occur for ARM encoding
1310 ALUWritePC(result); // setflags is always FALSE here
1311 else
1312 R[d] = result;
1313 if setflags then
1314 APSR.N = result<31>;
1315 APSR.Z = IsZeroBit(result);
1316 APSR.C = carry;
1317 APSR.V = overflow;
1318 }
1319#endif
1320
1321 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001322 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001323 if (!success)
1324 return false;
1325
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001326 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001327 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001328 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001329 if (!success)
1330 return false;
1331 uint32_t imm32;
1332 switch (encoding) {
1333 case eEncodingA1:
1334 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1335 break;
1336 default:
1337 return false;
1338 }
1339 addr_t ip_offset = imm32;
1340 addr_t addr = ip - ip_offset; // the adjusted ip value
1341
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001342 EmulateInstruction::Context context;
1343 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1344 Register dwarf_reg;
1345 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1346 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001348 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001349 return false;
1350 }
1351 return true;
1352}
1353
1354// Set ip to point to some stack offset.
1355// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001356bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001357EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001358{
1359#if 0
1360 // ARM pseudo code...
1361 if (ConditionPassed())
1362 {
1363 EncodingSpecificOperations();
1364 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1365 if d == 15 then // Can only occur for ARM encoding
1366 ALUWritePC(result); // setflags is always FALSE here
1367 else
1368 R[d] = result;
1369 if setflags then
1370 APSR.N = result<31>;
1371 APSR.Z = IsZeroBit(result);
1372 APSR.C = carry;
1373 APSR.V = overflow;
1374 }
1375#endif
1376
1377 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001378 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001379 if (!success)
1380 return false;
1381
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001382 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001383 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001384 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001385 if (!success)
1386 return false;
1387 uint32_t imm32;
1388 switch (encoding) {
1389 case eEncodingA1:
1390 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1391 break;
1392 default:
1393 return false;
1394 }
1395 addr_t sp_offset = imm32;
1396 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1397
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001398 EmulateInstruction::Context context;
1399 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1400 Register dwarf_reg;
1401 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1402 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001403
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001405 return false;
1406 }
1407 return true;
1408}
1409
Johnny Chenc9e747f2011-02-23 01:55:07 +00001410// This instruction subtracts an immediate value from the SP value, and writes
1411// the result to the destination register.
1412//
1413// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001414bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001415EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416{
1417#if 0
1418 // ARM pseudo code...
1419 if (ConditionPassed())
1420 {
1421 EncodingSpecificOperations();
1422 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001423 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001424 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001425 else
1426 R[d] = result;
1427 if setflags then
1428 APSR.N = result<31>;
1429 APSR.Z = IsZeroBit(result);
1430 APSR.C = carry;
1431 APSR.V = overflow;
1432 }
1433#endif
1434
1435 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001436 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001437 if (!success)
1438 return false;
1439
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001440 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001441 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001442 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001443 if (!success)
1444 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001445
1446 uint32_t Rd;
1447 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001448 uint32_t imm32;
1449 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001450 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001451 Rd = 13;
1452 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001453 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001454 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001455 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001456 Rd = Bits32(opcode, 11, 8);
1457 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001458 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001459 if (Rd == 15 && setflags)
1460 return EmulateCMPImm(eEncodingT2);
1461 if (Rd == 15 && !setflags)
1462 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001463 break;
1464 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001465 Rd = Bits32(opcode, 11, 8);
1466 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001467 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001468 if (Rd == 15)
1469 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001470 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001471 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001472 Rd = Bits32(opcode, 15, 12);
1473 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001474 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001475 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1476 // TODO: Emulate SUBS PC, LR and related instructions.
1477 if (Rd == 15 && setflags)
1478 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001479 break;
1480 default:
1481 return false;
1482 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001483 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1484
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001485 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001486 if (Rd == 13)
1487 {
1488 context.type = EmulateInstruction::eContextAdjustStackPointer;
1489 context.SetImmediateSigned (-imm32); // the stack pointer offset
1490 }
1491 else
1492 {
1493 context.type = EmulateInstruction::eContextImmediate;
1494 context.SetNoArgs ();
1495 }
1496
1497 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001498 return false;
1499 }
1500 return true;
1501}
1502
Johnny Chen08c25e82011-01-31 18:02:28 +00001503// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001504bool
1505EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001506{
1507#if 0
1508 // ARM pseudo code...
1509 if (ConditionPassed())
1510 {
1511 EncodingSpecificOperations();
1512 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1513 address = if index then offset_addr else R[n];
1514 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1515 if wback then R[n] = offset_addr;
1516 }
1517#endif
1518
1519 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001520 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001521 if (!success)
1522 return false;
1523
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001524 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001525 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001526 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001527 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001528 if (!success)
1529 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001530 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001531 uint32_t imm12;
1532 switch (encoding) {
1533 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001534 Rt = Bits32(opcode, 15, 12);
1535 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001536 break;
1537 default:
1538 return false;
1539 }
1540 addr_t sp_offset = imm12;
1541 addr_t addr = sp - sp_offset;
1542
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001543 EmulateInstruction::Context context;
1544 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1545 Register dwarf_reg;
1546 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001547 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001548 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001549 dwarf_reg.num = dwarf_r0 + Rt;
1550 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001551 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001552 if (!success)
1553 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001554 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001555 return false;
1556 }
1557 else
1558 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001559 dwarf_reg.num = dwarf_pc;
1560 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001561 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001562 if (!success)
1563 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001564 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001565 return false;
1566 }
1567
1568 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001569 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001570
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001571 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001572 return false;
1573 }
1574 return true;
1575}
1576
Johnny Chen08c25e82011-01-31 18:02:28 +00001577// Vector Push stores multiple extension registers to the stack.
1578// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001579bool
1580EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001581{
1582#if 0
1583 // ARM pseudo code...
1584 if (ConditionPassed())
1585 {
1586 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1587 address = SP - imm32;
1588 SP = SP - imm32;
1589 if single_regs then
1590 for r = 0 to regs-1
1591 MemA[address,4] = S[d+r]; address = address+4;
1592 else
1593 for r = 0 to regs-1
1594 // Store as two word-aligned words in the correct order for current endianness.
1595 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1596 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1597 address = address+8;
1598 }
1599#endif
1600
1601 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001602 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001603 if (!success)
1604 return false;
1605
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001606 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001607 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001608 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001609 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001610 if (!success)
1611 return false;
1612 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001613 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001614 uint32_t imm32; // stack offset
1615 uint32_t regs; // number of registers
1616 switch (encoding) {
1617 case eEncodingT1:
1618 case eEncodingA1:
1619 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001620 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001621 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1622 // If UInt(imm8) is odd, see "FSTMX".
1623 regs = Bits32(opcode, 7, 0) / 2;
1624 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1625 if (regs == 0 || regs > 16 || (d + regs) > 32)
1626 return false;
1627 break;
1628 case eEncodingT2:
1629 case eEncodingA2:
1630 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001631 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001632 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1633 regs = Bits32(opcode, 7, 0);
1634 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1635 if (regs == 0 || regs > 16 || (d + regs) > 32)
1636 return false;
1637 break;
1638 default:
1639 return false;
1640 }
1641 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1642 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1643 addr_t sp_offset = imm32;
1644 addr_t addr = sp - sp_offset;
1645 uint32_t i;
1646
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001647 EmulateInstruction::Context context;
1648 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1649 Register dwarf_reg;
1650 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001651 for (i=d; i<regs; ++i)
1652 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001653 dwarf_reg.num = start_reg + i;
1654 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001655 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001656 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001657 if (!success)
1658 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001659 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001660 return false;
1661 addr += reg_byte_size;
1662 }
1663
1664 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001665 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001666
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001667 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001668 return false;
1669 }
1670 return true;
1671}
1672
Johnny Chen587a0a42011-02-01 18:35:28 +00001673// Vector Pop loads multiple extension registers from the stack.
1674// It also updates SP to point just above the loaded data.
1675bool
1676EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1677{
1678#if 0
1679 // ARM pseudo code...
1680 if (ConditionPassed())
1681 {
1682 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1683 address = SP;
1684 SP = SP + imm32;
1685 if single_regs then
1686 for r = 0 to regs-1
1687 S[d+r] = MemA[address,4]; address = address+4;
1688 else
1689 for r = 0 to regs-1
1690 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1691 // Combine the word-aligned words in the correct order for current endianness.
1692 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1693 }
1694#endif
1695
1696 bool success = false;
1697 const uint32_t opcode = OpcodeAsUnsigned (&success);
1698 if (!success)
1699 return false;
1700
1701 if (ConditionPassed())
1702 {
1703 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001704 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001705 if (!success)
1706 return false;
1707 bool single_regs;
1708 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1709 uint32_t imm32; // stack offset
1710 uint32_t regs; // number of registers
1711 switch (encoding) {
1712 case eEncodingT1:
1713 case eEncodingA1:
1714 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001715 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001716 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1717 // If UInt(imm8) is odd, see "FLDMX".
1718 regs = Bits32(opcode, 7, 0) / 2;
1719 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1720 if (regs == 0 || regs > 16 || (d + regs) > 32)
1721 return false;
1722 break;
1723 case eEncodingT2:
1724 case eEncodingA2:
1725 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001726 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001727 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1728 regs = Bits32(opcode, 7, 0);
1729 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1730 if (regs == 0 || regs > 16 || (d + regs) > 32)
1731 return false;
1732 break;
1733 default:
1734 return false;
1735 }
1736 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1737 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1738 addr_t sp_offset = imm32;
1739 addr_t addr = sp;
1740 uint32_t i;
1741 uint64_t data; // uint64_t to accomodate 64-bit registers.
1742
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001743 EmulateInstruction::Context context;
1744 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1745 Register dwarf_reg;
1746 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001747 for (i=d; i<regs; ++i)
1748 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001749 dwarf_reg.num = start_reg + i;
1750 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001751 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001752 if (!success)
1753 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001754 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001755 return false;
1756 addr += reg_byte_size;
1757 }
1758
1759 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001760 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001761
1762 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1763 return false;
1764 }
1765 return true;
1766}
1767
Johnny Chenb77be412011-02-04 00:40:18 +00001768// SVC (previously SWI)
1769bool
1770EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1771{
1772#if 0
1773 // ARM pseudo code...
1774 if (ConditionPassed())
1775 {
1776 EncodingSpecificOperations();
1777 CallSupervisor();
1778 }
1779#endif
1780
1781 bool success = false;
1782 const uint32_t opcode = OpcodeAsUnsigned (&success);
1783 if (!success)
1784 return false;
1785
1786 if (ConditionPassed())
1787 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001788 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001789 addr_t lr; // next instruction address
1790 if (!success)
1791 return false;
1792 uint32_t imm32; // the immediate constant
1793 uint32_t mode; // ARM or Thumb mode
1794 switch (encoding) {
1795 case eEncodingT1:
1796 lr = (pc + 2) | 1u; // return address
1797 imm32 = Bits32(opcode, 7, 0);
1798 mode = eModeThumb;
1799 break;
1800 case eEncodingA1:
1801 lr = pc + 4; // return address
1802 imm32 = Bits32(opcode, 23, 0);
1803 mode = eModeARM;
1804 break;
1805 default:
1806 return false;
1807 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001808
1809 EmulateInstruction::Context context;
1810 context.type = EmulateInstruction::eContextSupervisorCall;
1811 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001812 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1813 return false;
1814 }
1815 return true;
1816}
1817
Johnny Chenc315f862011-02-05 00:46:10 +00001818// If Then makes up to four following instructions (the IT block) conditional.
1819bool
1820EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1821{
1822#if 0
1823 // ARM pseudo code...
1824 EncodingSpecificOperations();
1825 ITSTATE.IT<7:0> = firstcond:mask;
1826#endif
1827
1828 bool success = false;
1829 const uint32_t opcode = OpcodeAsUnsigned (&success);
1830 if (!success)
1831 return false;
1832
1833 m_it_session.InitIT(Bits32(opcode, 7, 0));
1834 return true;
1835}
1836
Johnny Chen3b620b32011-02-07 20:11:47 +00001837// Branch causes a branch to a target address.
1838bool
1839EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1840{
1841#if 0
1842 // ARM pseudo code...
1843 if (ConditionPassed())
1844 {
1845 EncodingSpecificOperations();
1846 BranchWritePC(PC + imm32);
1847 }
1848#endif
1849
1850 bool success = false;
1851 const uint32_t opcode = OpcodeAsUnsigned (&success);
1852 if (!success)
1853 return false;
1854
Johnny Chen9ee056b2011-02-08 00:06:35 +00001855 if (ConditionPassed())
1856 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001857 EmulateInstruction::Context context;
1858 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001859 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001860 if (!success)
1861 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001862 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001863 int32_t imm32; // PC-relative offset
1864 switch (encoding) {
1865 case eEncodingT1:
1866 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1867 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001868 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001869 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001870 break;
1871 case eEncodingT2:
1872 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001873 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001874 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001875 break;
1876 case eEncodingT3:
1877 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1878 {
Johnny Chenbd599902011-02-10 21:39:01 +00001879 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001880 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001881 uint32_t J1 = Bit32(opcode, 13);
1882 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001883 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001884 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001885 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001886 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001887 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001888 break;
1889 }
1890 case eEncodingT4:
1891 {
Johnny Chenbd599902011-02-10 21:39:01 +00001892 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001893 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001894 uint32_t J1 = Bit32(opcode, 13);
1895 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001896 uint32_t imm11 = Bits32(opcode, 10, 0);
1897 uint32_t I1 = !(J1 ^ S);
1898 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001899 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001900 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001901 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001902 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001903 break;
1904 }
1905 case eEncodingA1:
1906 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001907 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001908 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001909 break;
1910 default:
1911 return false;
1912 }
1913 if (!BranchWritePC(context, target))
1914 return false;
1915 }
1916 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001917}
1918
Johnny Chen53ebab72011-02-08 23:21:57 +00001919// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1920// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1921// CBNZ, CBZ
1922bool
1923EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1924{
1925#if 0
1926 // ARM pseudo code...
1927 EncodingSpecificOperations();
1928 if nonzero ^ IsZero(R[n]) then
1929 BranchWritePC(PC + imm32);
1930#endif
1931
1932 bool success = false;
1933 const uint32_t opcode = OpcodeAsUnsigned (&success);
1934 if (!success)
1935 return false;
1936
1937 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00001938 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001939 if (!success)
1940 return false;
1941
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001942 EmulateInstruction::Context context;
1943 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001944 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001945 if (!success)
1946 return false;
1947
1948 addr_t target; // target address
1949 uint32_t imm32; // PC-relative offset to branch forward
1950 bool nonzero;
1951 switch (encoding) {
1952 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001953 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001954 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00001955 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001956 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001957 break;
1958 default:
1959 return false;
1960 }
1961 if (nonzero ^ (reg_val == 0))
1962 if (!BranchWritePC(context, target))
1963 return false;
1964
1965 return true;
1966}
1967
Johnny Chen60299ec2011-02-17 19:34:27 +00001968// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1969// A base register provides a pointer to the table, and a second register supplies an index into the table.
1970// The branch length is twice the value of the byte returned from the table.
1971//
1972// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1973// A base register provides a pointer to the table, and a second register supplies an index into the table.
1974// The branch length is twice the value of the halfword returned from the table.
1975// TBB, TBH
1976bool
1977EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1978{
1979#if 0
1980 // ARM pseudo code...
1981 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1982 if is_tbh then
1983 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1984 else
1985 halfwords = UInt(MemU[R[n]+R[m], 1]);
1986 BranchWritePC(PC + 2*halfwords);
1987#endif
1988
1989 bool success = false;
1990 const uint32_t opcode = OpcodeAsUnsigned (&success);
1991 if (!success)
1992 return false;
1993
1994 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1995 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1996 bool is_tbh; // true if table branch halfword
1997 switch (encoding) {
1998 case eEncodingT1:
1999 Rn = Bits32(opcode, 19, 16);
2000 Rm = Bits32(opcode, 3, 0);
2001 is_tbh = BitIsSet(opcode, 4);
2002 if (Rn == 13 || BadReg(Rm))
2003 return false;
2004 if (InITBlock() && !LastInITBlock())
2005 return false;
2006 break;
2007 default:
2008 return false;
2009 }
2010
2011 // Read the address of the table from the operand register Rn.
2012 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002013 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002014 if (!success)
2015 return false;
2016
2017 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002018 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002019 if (!success)
2020 return false;
2021
2022 // the offsetted table address
2023 addr_t addr = base + (is_tbh ? index*2 : index);
2024
2025 // PC-relative offset to branch forward
2026 EmulateInstruction::Context context;
2027 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002028 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002029 if (!success)
2030 return false;
2031
Johnny Chene39f22d2011-02-19 01:36:13 +00002032 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002033 if (!success)
2034 return false;
2035
2036 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002037 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002038 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2039 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2040
2041 if (!BranchWritePC(context, target))
2042 return false;
2043
2044 return true;
2045}
2046
Johnny Chen8fa20592011-02-18 01:22:22 +00002047// This instruction adds an immediate value to a register value, and writes the result to the destination
2048// register. It can optionally update the condition flags based on the result.
2049bool
2050EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2051{
2052#if 0
2053 // ARM pseudo code...
2054 if ConditionPassed() then
2055 EncodingSpecificOperations();
2056 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2057 if d == 15 then
2058 ALUWritePC(result); // setflags is always FALSE here
2059 else
2060 R[d] = result;
2061 if setflags then
2062 APSR.N = result<31>;
2063 APSR.Z = IsZeroBit(result);
2064 APSR.C = carry;
2065 APSR.V = overflow;
2066#endif
2067
2068 bool success = false;
2069 const uint32_t opcode = OpcodeAsUnsigned (&success);
2070 if (!success)
2071 return false;
2072
2073 if (ConditionPassed())
2074 {
2075 uint32_t Rd, Rn;
2076 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2077 bool setflags;
2078 switch (encoding)
2079 {
2080 case eEncodingA1:
2081 Rd = Bits32(opcode, 15, 12);
2082 Rn = Bits32(opcode, 19, 16);
2083 setflags = BitIsSet(opcode, 20);
2084 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2085 break;
2086 default:
2087 return false;
2088 }
2089
Johnny Chen8fa20592011-02-18 01:22:22 +00002090 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002091 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002092 if (!success)
2093 return false;
2094
2095 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2096
2097 EmulateInstruction::Context context;
2098 context.type = EmulateInstruction::eContextImmediate;
2099 context.SetNoArgs ();
2100
2101 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2102 return false;
2103 }
2104 return true;
2105}
2106
Johnny Chend761dcf2011-02-17 22:03:29 +00002107// This instruction adds a register value and an optionally-shifted register value, and writes the result
2108// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002109bool
Johnny Chen9f687722011-02-18 00:02:28 +00002110EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002111{
2112#if 0
2113 // ARM pseudo code...
2114 if ConditionPassed() then
2115 EncodingSpecificOperations();
2116 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2117 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2118 if d == 15 then
2119 ALUWritePC(result); // setflags is always FALSE here
2120 else
2121 R[d] = result;
2122 if setflags then
2123 APSR.N = result<31>;
2124 APSR.Z = IsZeroBit(result);
2125 APSR.C = carry;
2126 APSR.V = overflow;
2127#endif
2128
2129 bool success = false;
2130 const uint32_t opcode = OpcodeAsUnsigned (&success);
2131 if (!success)
2132 return false;
2133
2134 if (ConditionPassed())
2135 {
2136 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002137 ARM_ShifterType shift_t;
2138 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002139 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002140 switch (encoding)
2141 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002142 case eEncodingT1:
2143 Rd = Bits32(opcode, 2, 0);
2144 Rn = Bits32(opcode, 5, 3);
2145 Rm = Bits32(opcode, 8, 6);
2146 setflags = !InITBlock();
2147 shift_t = SRType_LSL;
2148 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002149 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002150 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002151 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002152 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002153 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002154 shift_t = SRType_LSL;
2155 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002156 if (Rn == 15 && Rm == 15)
2157 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002158 if (Rd == 15 && InITBlock() && !LastInITBlock())
2159 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002160 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002161 case eEncodingA1:
2162 Rd = Bits32(opcode, 15, 12);
2163 Rn = Bits32(opcode, 19, 16);
2164 Rm = Bits32(opcode, 3, 0);
2165 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002166 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002167 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002168 default:
2169 return false;
2170 }
2171
Johnny Chen26863dc2011-02-09 23:43:29 +00002172 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002173 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002174 if (!success)
2175 return false;
2176
2177 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002178 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002179 if (!success)
2180 return false;
2181
Johnny Chene97c0d52011-02-18 19:32:20 +00002182 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002183 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002184
2185 EmulateInstruction::Context context;
2186 context.type = EmulateInstruction::eContextImmediate;
2187 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002188
Johnny Chen10530c22011-02-17 22:37:12 +00002189 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002190 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002191 }
2192 return true;
2193}
2194
Johnny Chen34075cb2011-02-22 01:56:31 +00002195// Compare Negative (immediate) adds a register value and an immediate value.
2196// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002197bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002198EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2199{
2200#if 0
2201 // ARM pseudo code...
2202 if ConditionPassed() then
2203 EncodingSpecificOperations();
2204 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2205 APSR.N = result<31>;
2206 APSR.Z = IsZeroBit(result);
2207 APSR.C = carry;
2208 APSR.V = overflow;
2209#endif
2210
2211 bool success = false;
2212 const uint32_t opcode = OpcodeAsUnsigned (&success);
2213 if (!success)
2214 return false;
2215
2216 uint32_t Rn; // the first operand
2217 uint32_t imm32; // the immediate value to be compared with
2218 switch (encoding) {
2219 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002220 Rn = Bits32(opcode, 19, 16);
2221 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2222 if (Rn == 15)
2223 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002224 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002225 case eEncodingA1:
2226 Rn = Bits32(opcode, 19, 16);
2227 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2228 break;
2229 default:
2230 return false;
2231 }
2232 // Read the register value from the operand register Rn.
2233 uint32_t reg_val = ReadCoreReg(Rn, &success);
2234 if (!success)
2235 return false;
2236
Johnny Chen078fbc62011-02-22 19:48:22 +00002237 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002238
2239 EmulateInstruction::Context context;
2240 context.type = EmulateInstruction::eContextImmediate;
2241 context.SetNoArgs ();
2242 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2243 return false;
2244
2245 return true;
2246}
2247
2248// Compare Negative (register) adds a register value and an optionally-shifted register value.
2249// It updates the condition flags based on the result, and discards the result.
2250bool
2251EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2252{
2253#if 0
2254 // ARM pseudo code...
2255 if ConditionPassed() then
2256 EncodingSpecificOperations();
2257 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2258 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2259 APSR.N = result<31>;
2260 APSR.Z = IsZeroBit(result);
2261 APSR.C = carry;
2262 APSR.V = overflow;
2263#endif
2264
2265 bool success = false;
2266 const uint32_t opcode = OpcodeAsUnsigned (&success);
2267 if (!success)
2268 return false;
2269
2270 uint32_t Rn; // the first operand
2271 uint32_t Rm; // the second operand
2272 ARM_ShifterType shift_t;
2273 uint32_t shift_n; // the shift applied to the value read from Rm
2274 switch (encoding) {
2275 case eEncodingT1:
2276 Rn = Bits32(opcode, 2, 0);
2277 Rm = Bits32(opcode, 5, 3);
2278 shift_t = SRType_LSL;
2279 shift_n = 0;
2280 break;
2281 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002282 Rn = Bits32(opcode, 19, 16);
2283 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002284 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002285 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2286 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002287 return false;
2288 break;
2289 case eEncodingA1:
2290 Rn = Bits32(opcode, 19, 16);
2291 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002292 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002293 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002294 default:
2295 return false;
2296 }
2297 // Read the register value from register Rn.
2298 uint32_t val1 = ReadCoreReg(Rn, &success);
2299 if (!success)
2300 return false;
2301
2302 // Read the register value from register Rm.
2303 uint32_t val2 = ReadCoreReg(Rm, &success);
2304 if (!success)
2305 return false;
2306
2307 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002308 AddWithCarryResult res = AddWithCarry(val1, shifted, 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 (immediate) subtracts an immediate value from a register value.
2320// It updates the condition flags based on the result, and discards the result.
2321bool
2322EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002323{
2324#if 0
2325 // ARM pseudo code...
2326 if ConditionPassed() then
2327 EncodingSpecificOperations();
2328 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2329 APSR.N = result<31>;
2330 APSR.Z = IsZeroBit(result);
2331 APSR.C = carry;
2332 APSR.V = overflow;
2333#endif
2334
2335 bool success = false;
2336 const uint32_t opcode = OpcodeAsUnsigned (&success);
2337 if (!success)
2338 return false;
2339
2340 uint32_t Rn; // the first operand
2341 uint32_t imm32; // the immediate value to be compared with
2342 switch (encoding) {
2343 case eEncodingT1:
2344 Rn = Bits32(opcode, 10, 8);
2345 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002346 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002347 case eEncodingT2:
2348 Rn = Bits32(opcode, 19, 16);
2349 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2350 if (Rn == 15)
2351 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002352 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002353 case eEncodingA1:
2354 Rn = Bits32(opcode, 19, 16);
2355 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002356 break;
2357 default:
2358 return false;
2359 }
2360 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002361 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002362 if (!success)
2363 return false;
2364
Johnny Chen10530c22011-02-17 22:37:12 +00002365 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2366
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002367 EmulateInstruction::Context context;
2368 context.type = EmulateInstruction::eContextImmediate;
2369 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002370 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2371 return false;
2372
Johnny Chend4dc4442011-02-11 02:02:56 +00002373 return true;
2374}
2375
Johnny Chen34075cb2011-02-22 01:56:31 +00002376// Compare (register) subtracts an optionally-shifted register value from a register value.
2377// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002378bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002379EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002380{
2381#if 0
2382 // ARM pseudo code...
2383 if ConditionPassed() then
2384 EncodingSpecificOperations();
2385 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2386 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2387 APSR.N = result<31>;
2388 APSR.Z = IsZeroBit(result);
2389 APSR.C = carry;
2390 APSR.V = overflow;
2391#endif
2392
2393 bool success = false;
2394 const uint32_t opcode = OpcodeAsUnsigned (&success);
2395 if (!success)
2396 return false;
2397
2398 uint32_t Rn; // the first operand
2399 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002400 ARM_ShifterType shift_t;
2401 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002402 switch (encoding) {
2403 case eEncodingT1:
2404 Rn = Bits32(opcode, 2, 0);
2405 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002406 shift_t = SRType_LSL;
2407 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002408 break;
2409 case eEncodingT2:
2410 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2411 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002412 shift_t = SRType_LSL;
2413 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002414 if (Rn < 8 && Rm < 8)
2415 return false;
2416 if (Rn == 15 || Rm == 15)
2417 return false;
2418 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002419 case eEncodingA1:
2420 Rn = Bits32(opcode, 19, 16);
2421 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002422 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002423 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002424 default:
2425 return false;
2426 }
2427 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002428 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002429 if (!success)
2430 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002431
Johnny Chene4a4d302011-02-11 21:53:58 +00002432 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002433 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002434 if (!success)
2435 return false;
2436
Johnny Chen34075cb2011-02-22 01:56:31 +00002437 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2438 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002439
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002440 EmulateInstruction::Context context;
2441 context.type = EmulateInstruction::eContextImmediate;
2442 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002443 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2444 return false;
2445
Johnny Chene4a4d302011-02-11 21:53:58 +00002446 return true;
2447}
2448
Johnny Chen82f16aa2011-02-15 20:10:55 +00002449// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2450// shifting in copies of its sign bit, and writes the result to the destination register. It can
2451// optionally update the condition flags based on the result.
2452bool
2453EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2454{
2455#if 0
2456 // ARM pseudo code...
2457 if ConditionPassed() then
2458 EncodingSpecificOperations();
2459 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2460 if d == 15 then // Can only occur for ARM encoding
2461 ALUWritePC(result); // setflags is always FALSE here
2462 else
2463 R[d] = result;
2464 if setflags then
2465 APSR.N = result<31>;
2466 APSR.Z = IsZeroBit(result);
2467 APSR.C = carry;
2468 // APSR.V unchanged
2469#endif
2470
Johnny Chen41a0a152011-02-16 01:27:54 +00002471 return EmulateShiftImm(encoding, SRType_ASR);
2472}
2473
2474// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2475// shifting in copies of its sign bit, and writes the result to the destination register.
2476// The variable number of bits is read from the bottom byte of a register. It can optionally update
2477// the condition flags based on the result.
2478bool
2479EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2480{
2481#if 0
2482 // ARM pseudo code...
2483 if ConditionPassed() then
2484 EncodingSpecificOperations();
2485 shift_n = UInt(R[m]<7:0>);
2486 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2487 R[d] = result;
2488 if setflags then
2489 APSR.N = result<31>;
2490 APSR.Z = IsZeroBit(result);
2491 APSR.C = carry;
2492 // APSR.V unchanged
2493#endif
2494
2495 return EmulateShiftReg(encoding, SRType_ASR);
2496}
2497
2498// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2499// shifting in zeros, and writes the result to the destination register. It can optionally
2500// update the condition flags based on the result.
2501bool
2502EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2503{
2504#if 0
2505 // ARM pseudo code...
2506 if ConditionPassed() then
2507 EncodingSpecificOperations();
2508 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2509 if d == 15 then // Can only occur for ARM encoding
2510 ALUWritePC(result); // setflags is always FALSE here
2511 else
2512 R[d] = result;
2513 if setflags then
2514 APSR.N = result<31>;
2515 APSR.Z = IsZeroBit(result);
2516 APSR.C = carry;
2517 // APSR.V unchanged
2518#endif
2519
2520 return EmulateShiftImm(encoding, SRType_LSL);
2521}
2522
2523// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2524// shifting in zeros, and writes the result to the destination register. The variable number
2525// of bits is read from the bottom byte of a register. It can optionally update the condition
2526// flags based on the result.
2527bool
2528EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2529{
2530#if 0
2531 // ARM pseudo code...
2532 if ConditionPassed() then
2533 EncodingSpecificOperations();
2534 shift_n = UInt(R[m]<7:0>);
2535 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2536 R[d] = result;
2537 if setflags then
2538 APSR.N = result<31>;
2539 APSR.Z = IsZeroBit(result);
2540 APSR.C = carry;
2541 // APSR.V unchanged
2542#endif
2543
2544 return EmulateShiftReg(encoding, SRType_LSL);
2545}
2546
2547// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2548// shifting in zeros, and writes the result to the destination register. It can optionally
2549// update the condition flags based on the result.
2550bool
2551EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2552{
2553#if 0
2554 // ARM pseudo code...
2555 if ConditionPassed() then
2556 EncodingSpecificOperations();
2557 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2558 if d == 15 then // Can only occur for ARM encoding
2559 ALUWritePC(result); // setflags is always FALSE here
2560 else
2561 R[d] = result;
2562 if setflags then
2563 APSR.N = result<31>;
2564 APSR.Z = IsZeroBit(result);
2565 APSR.C = carry;
2566 // APSR.V unchanged
2567#endif
2568
2569 return EmulateShiftImm(encoding, SRType_LSR);
2570}
2571
2572// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2573// shifting in zeros, and writes the result to the destination register. The variable number
2574// of bits is read from the bottom byte of a register. It can optionally update the condition
2575// flags based on the result.
2576bool
2577EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2578{
2579#if 0
2580 // ARM pseudo code...
2581 if ConditionPassed() then
2582 EncodingSpecificOperations();
2583 shift_n = UInt(R[m]<7:0>);
2584 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2585 R[d] = result;
2586 if setflags then
2587 APSR.N = result<31>;
2588 APSR.Z = IsZeroBit(result);
2589 APSR.C = carry;
2590 // APSR.V unchanged
2591#endif
2592
2593 return EmulateShiftReg(encoding, SRType_LSR);
2594}
2595
Johnny Cheneeab4852011-02-16 22:14:44 +00002596// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2597// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2598// It can optionally update the condition flags based on the result.
2599bool
2600EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2601{
2602#if 0
2603 // ARM pseudo code...
2604 if ConditionPassed() then
2605 EncodingSpecificOperations();
2606 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2607 if d == 15 then // Can only occur for ARM encoding
2608 ALUWritePC(result); // setflags is always FALSE here
2609 else
2610 R[d] = result;
2611 if setflags then
2612 APSR.N = result<31>;
2613 APSR.Z = IsZeroBit(result);
2614 APSR.C = carry;
2615 // APSR.V unchanged
2616#endif
2617
2618 return EmulateShiftImm(encoding, SRType_ROR);
2619}
2620
2621// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2622// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2623// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2624// flags based on the result.
2625bool
2626EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2627{
2628#if 0
2629 // ARM pseudo code...
2630 if ConditionPassed() then
2631 EncodingSpecificOperations();
2632 shift_n = UInt(R[m]<7:0>);
2633 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2634 R[d] = result;
2635 if setflags then
2636 APSR.N = result<31>;
2637 APSR.Z = IsZeroBit(result);
2638 APSR.C = carry;
2639 // APSR.V unchanged
2640#endif
2641
2642 return EmulateShiftReg(encoding, SRType_ROR);
2643}
2644
2645// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2646// with the carry flag shifted into bit [31].
2647//
2648// RRX can optionally update the condition flags based on the result.
2649// In that case, bit [0] is shifted into the carry flag.
2650bool
2651EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2652{
2653#if 0
2654 // ARM pseudo code...
2655 if ConditionPassed() then
2656 EncodingSpecificOperations();
2657 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2658 if d == 15 then // Can only occur for ARM encoding
2659 ALUWritePC(result); // setflags is always FALSE here
2660 else
2661 R[d] = result;
2662 if setflags then
2663 APSR.N = result<31>;
2664 APSR.Z = IsZeroBit(result);
2665 APSR.C = carry;
2666 // APSR.V unchanged
2667#endif
2668
2669 return EmulateShiftImm(encoding, SRType_RRX);
2670}
2671
Johnny Chen41a0a152011-02-16 01:27:54 +00002672bool
2673EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2674{
2675 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2676
Johnny Chen82f16aa2011-02-15 20:10:55 +00002677 bool success = false;
2678 const uint32_t opcode = OpcodeAsUnsigned (&success);
2679 if (!success)
2680 return false;
2681
2682 if (ConditionPassed())
2683 {
Johnny Chene7f89532011-02-15 23:22:46 +00002684 uint32_t Rd; // the destination register
2685 uint32_t Rm; // the first operand register
2686 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002687 uint32_t carry; // the carry bit after the shift operation
2688 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002689
2690 // Special case handling!
2691 // A8.6.139 ROR (immediate) -- Encoding T1
2692 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2693 {
2694 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2695 // have the same decoding of bit fields as the other Thumb2 shift operations.
2696 encoding = eEncodingT2;
2697 }
2698
Johnny Chen82f16aa2011-02-15 20:10:55 +00002699 switch (encoding) {
2700 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002701 // Due to the above special case handling!
2702 assert(shift_type != SRType_ROR);
2703
Johnny Chen82f16aa2011-02-15 20:10:55 +00002704 Rd = Bits32(opcode, 2, 0);
2705 Rm = Bits32(opcode, 5, 3);
2706 setflags = !InITBlock();
2707 imm5 = Bits32(opcode, 10, 6);
2708 break;
2709 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002710 // A8.6.141 RRX
2711 assert(shift_type != SRType_RRX);
2712
Johnny Chen82f16aa2011-02-15 20:10:55 +00002713 Rd = Bits32(opcode, 11, 8);
2714 Rm = Bits32(opcode, 3, 0);
2715 setflags = BitIsSet(opcode, 20);
2716 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2717 if (BadReg(Rd) || BadReg(Rm))
2718 return false;
2719 break;
2720 case eEncodingA1:
2721 Rd = Bits32(opcode, 15, 12);
2722 Rm = Bits32(opcode, 3, 0);
2723 setflags = BitIsSet(opcode, 20);
2724 imm5 = Bits32(opcode, 11, 7);
2725 break;
2726 default:
2727 return false;
2728 }
2729
Johnny Cheneeab4852011-02-16 22:14:44 +00002730 // A8.6.139 ROR (immediate)
2731 if (shift_type == SRType_ROR && imm5 == 0)
2732 shift_type = SRType_RRX;
2733
Johnny Chen82f16aa2011-02-15 20:10:55 +00002734 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002735 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002736 if (!success)
2737 return false;
2738
Johnny Cheneeab4852011-02-16 22:14:44 +00002739 // Decode the shift amount if not RRX.
2740 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002741
Johnny Chene97c0d52011-02-18 19:32:20 +00002742 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002743
2744 // The context specifies that an immediate is to be moved into Rd.
2745 EmulateInstruction::Context context;
2746 context.type = EmulateInstruction::eContextImmediate;
2747 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002748
Johnny Chen10530c22011-02-17 22:37:12 +00002749 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002750 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002751 }
2752 return true;
2753}
2754
Johnny Chene7f89532011-02-15 23:22:46 +00002755bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002756EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002757{
Johnny Chen41a0a152011-02-16 01:27:54 +00002758 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002759
2760 bool success = false;
2761 const uint32_t opcode = OpcodeAsUnsigned (&success);
2762 if (!success)
2763 return false;
2764
2765 if (ConditionPassed())
2766 {
2767 uint32_t Rd; // the destination register
2768 uint32_t Rn; // the first operand register
2769 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2770 uint32_t carry; // the carry bit after the shift operation
2771 bool setflags;
2772 switch (encoding) {
2773 case eEncodingT1:
2774 Rd = Bits32(opcode, 2, 0);
2775 Rn = Rd;
2776 Rm = Bits32(opcode, 5, 3);
2777 setflags = !InITBlock();
2778 break;
2779 case eEncodingT2:
2780 Rd = Bits32(opcode, 11, 8);
2781 Rn = Bits32(opcode, 19, 16);
2782 Rm = Bits32(opcode, 3, 0);
2783 setflags = BitIsSet(opcode, 20);
2784 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2785 return false;
2786 break;
2787 case eEncodingA1:
2788 Rd = Bits32(opcode, 15, 12);
2789 Rn = Bits32(opcode, 3, 0);
2790 Rm = Bits32(opcode, 11, 8);
2791 setflags = BitIsSet(opcode, 20);
2792 if (Rd == 15 || Rn == 15 || Rm == 15)
2793 return false;
2794 break;
2795 default:
2796 return false;
2797 }
2798
2799 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002800 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002801 if (!success)
2802 return false;
2803 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002804 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002805 if (!success)
2806 return false;
2807
2808 // Get the shift amount.
2809 uint32_t amt = Bits32(val, 7, 0);
2810
Johnny Chene97c0d52011-02-18 19:32:20 +00002811 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002812
2813 // The context specifies that an immediate is to be moved into Rd.
2814 EmulateInstruction::Context context;
2815 context.type = EmulateInstruction::eContextImmediate;
2816 context.SetNoArgs ();
2817
Johnny Chen10530c22011-02-17 22:37:12 +00002818 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002819 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002820 }
2821 return true;
2822}
2823
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002824// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002825// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002826// can be written back to the base register.
2827bool
2828EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2829{
2830#if 0
2831 // ARM pseudo code...
2832 if ConditionPassed()
2833 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2834 address = R[n];
2835
2836 for i = 0 to 14
2837 if registers<i> == '1' then
2838 R[i] = MemA[address, 4]; address = address + 4;
2839 if registers<15> == '1' then
2840 LoadWritePC (MemA[address, 4]);
2841
2842 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2843 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2844
2845#endif
2846
2847 bool success = false;
2848 const uint32_t opcode = OpcodeAsUnsigned (&success);
2849 if (!success)
2850 return false;
2851
2852 if (ConditionPassed())
2853 {
2854 uint32_t n;
2855 uint32_t registers = 0;
2856 bool wback;
2857 const uint32_t addr_byte_size = GetAddressByteSize();
2858 switch (encoding)
2859 {
2860 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002861 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002862 n = Bits32 (opcode, 10, 8);
2863 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002864 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002865 wback = BitIsClear (registers, n);
2866 // if BitCount(registers) < 1 then UNPREDICTABLE;
2867 if (BitCount(registers) < 1)
2868 return false;
2869 break;
2870 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002871 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2872 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002873 n = Bits32 (opcode, 19, 16);
2874 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002875 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002876 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002877
2878 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002879 if ((n == 15)
2880 || (BitCount (registers) < 2)
2881 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2882 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002883
2884 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002885 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002886 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002887
2888 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002889 if (wback
2890 && BitIsSet (registers, n))
2891 return false;
2892 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002893
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002894 case eEncodingA1:
2895 n = Bits32 (opcode, 19, 16);
2896 registers = Bits32 (opcode, 15, 0);
2897 wback = BitIsSet (opcode, 21);
2898 if ((n == 15)
2899 || (BitCount (registers) < 1))
2900 return false;
2901 break;
2902 default:
2903 return false;
2904 }
2905
2906 int32_t offset = 0;
2907 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2908 if (!success)
2909 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002910
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002911 EmulateInstruction::Context context;
2912 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2913 Register dwarf_reg;
2914 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2915 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002916
2917 for (int i = 0; i < 14; ++i)
2918 {
2919 if (BitIsSet (registers, i))
2920 {
Caroline Tice85aab332011-02-08 23:56:10 +00002921 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002922 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002923 if (wback && (n == 13)) // Pop Instruction
2924 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2925
2926 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002927 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002928 if (!success)
2929 return false;
2930
2931 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2932 return false;
2933
2934 offset += addr_byte_size;
2935 }
2936 }
2937
2938 if (BitIsSet (registers, 15))
2939 {
2940 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002941 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002942 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002943 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002944 if (!success)
2945 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002946 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002947 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002948 return false;
2949 }
2950
2951 if (wback && BitIsClear (registers, n))
2952 {
Caroline Ticefa172202011-02-11 22:49:54 +00002953 // R[n] = R[n] + 4 * BitCount (registers)
2954 int32_t offset = addr_byte_size * BitCount (registers);
2955 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002956 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002957
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002958 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2959 return false;
2960 }
2961 if (wback && BitIsSet (registers, n))
2962 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002963 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002964 }
2965 return true;
2966}
Caroline Tice713c2662011-02-11 17:59:55 +00002967
2968// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2969// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2970// can optionally be written back tot he base registers.
2971bool
2972EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2973{
2974#if 0
2975 // ARM pseudo code...
2976 if ConditionPassed() then
2977 EncodingSpecificOperations();
2978 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002979
Caroline Tice713c2662011-02-11 17:59:55 +00002980 for i = 0 to 14
2981 if registers<i> == ’1’ then
2982 R[i] = MemA[address,4]; address = address + 4;
2983
2984 if registers<15> == ’1’ then
2985 LoadWritePC(MemA[address,4]);
2986
2987 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2988 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2989#endif
2990
2991 bool success = false;
2992 const uint32_t opcode = OpcodeAsUnsigned (&success);
2993 if (!success)
2994 return false;
2995
2996 if (ConditionPassed())
2997 {
2998 uint32_t n;
2999 uint32_t registers = 0;
3000 bool wback;
3001 const uint32_t addr_byte_size = GetAddressByteSize();
3002
3003 // EncodingSpecificOperations();
3004 switch (encoding)
3005 {
3006 case eEncodingA1:
3007 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3008 n = Bits32 (opcode, 19, 16);
3009 registers = Bits32 (opcode, 15, 0);
3010 wback = BitIsSet (opcode, 21);
3011
3012 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3013 if ((n == 15) || (BitCount (registers) < 1))
3014 return false;
3015
3016 break;
3017
3018 default:
3019 return false;
3020 }
3021 // address = R[n] - 4*BitCount(registers) + 4;
3022
3023 int32_t offset = 0;
3024 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3025
3026 if (!success)
3027 return false;
3028
3029 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3030
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003031 EmulateInstruction::Context context;
3032 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3033 Register dwarf_reg;
3034 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3035 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003036
3037 // for i = 0 to 14
3038 for (int i = 0; i < 14; ++i)
3039 {
3040 // if registers<i> == ’1’ then
3041 if (BitIsSet (registers, i))
3042 {
3043 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003044 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003045 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003046 if (!success)
3047 return false;
3048 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3049 return false;
3050 offset += addr_byte_size;
3051 }
3052 }
3053
3054 // if registers<15> == ’1’ then
3055 // LoadWritePC(MemA[address,4]);
3056 if (BitIsSet (registers, 15))
3057 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003058 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003059 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003060 if (!success)
3061 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003062 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003063 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003064 return false;
3065 }
3066
3067 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3068 if (wback && BitIsClear (registers, n))
3069 {
Caroline Tice713c2662011-02-11 17:59:55 +00003070 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3071 if (!success)
3072 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003073
3074 offset = (addr_byte_size * BitCount (registers)) * -1;
3075 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003076 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003077 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003078 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3079 return false;
3080 }
3081
3082 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3083 if (wback && BitIsSet (registers, n))
3084 return WriteBits32Unknown (n);
3085 }
3086 return true;
3087}
3088
3089// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3090// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3091// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003092bool
3093EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3094{
3095#if 0
3096 // ARM pseudo code...
3097 if ConditionPassed() then
3098 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3099 address = R[n] - 4*BitCount(registers);
3100
3101 for i = 0 to 14
3102 if registers<i> == ’1’ then
3103 R[i] = MemA[address,4]; address = address + 4;
3104 if registers<15> == ’1’ then
3105 LoadWritePC(MemA[address,4]);
3106
3107 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3108 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3109#endif
3110
3111 bool success = false;
3112 const uint32_t opcode = OpcodeAsUnsigned (&success);
3113 if (!success)
3114 return false;
3115
3116 if (ConditionPassed())
3117 {
3118 uint32_t n;
3119 uint32_t registers = 0;
3120 bool wback;
3121 const uint32_t addr_byte_size = GetAddressByteSize();
3122 switch (encoding)
3123 {
3124 case eEncodingT1:
3125 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3126 n = Bits32 (opcode, 19, 16);
3127 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003128 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003129 wback = BitIsSet (opcode, 21);
3130
3131 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3132 if ((n == 15)
3133 || (BitCount (registers) < 2)
3134 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3135 return false;
3136
3137 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003138 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003139 return false;
3140
3141 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3142 if (wback && BitIsSet (registers, n))
3143 return false;
3144
3145 break;
3146
3147 case eEncodingA1:
3148 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3149 n = Bits32 (opcode, 19, 16);
3150 registers = Bits32 (opcode, 15, 0);
3151 wback = BitIsSet (opcode, 21);
3152
3153 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3154 if ((n == 15) || (BitCount (registers) < 1))
3155 return false;
3156
3157 break;
3158
3159 default:
3160 return false;
3161 }
3162
Caroline Tice713c2662011-02-11 17:59:55 +00003163 // address = R[n] - 4*BitCount(registers);
3164
Caroline Tice0b29e242011-02-08 23:16:02 +00003165 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003166 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3167
3168 if (!success)
3169 return false;
3170
3171 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003172 EmulateInstruction::Context context;
3173 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3174 Register dwarf_reg;
3175 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3176 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003177
3178 for (int i = 0; i < 14; ++i)
3179 {
3180 if (BitIsSet (registers, i))
3181 {
3182 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003183 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003184 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003185 if (!success)
3186 return false;
3187
3188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3189 return false;
3190
3191 offset += addr_byte_size;
3192 }
3193 }
3194
3195 // if registers<15> == ’1’ then
3196 // LoadWritePC(MemA[address,4]);
3197 if (BitIsSet (registers, 15))
3198 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003199 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003200 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003201 if (!success)
3202 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003203 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003204 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003205 return false;
3206 }
3207
3208 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3209 if (wback && BitIsClear (registers, n))
3210 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003211 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3212 if (!success)
3213 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003214
3215 offset = (addr_byte_size * BitCount (registers)) * -1;
3216 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003217 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003218 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003219 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3220 return false;
3221 }
3222
3223 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3224 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003225 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003226 }
3227 return true;
3228}
Caroline Tice85aab332011-02-08 23:56:10 +00003229
Caroline Tice713c2662011-02-11 17:59:55 +00003230// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3231// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3232// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003233bool
3234EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3235{
3236#if 0
3237 if ConditionPassed() then
3238 EncodingSpecificOperations();
3239 address = R[n] + 4;
3240
3241 for i = 0 to 14
3242 if registers<i> == ’1’ then
3243 R[i] = MemA[address,4]; address = address + 4;
3244 if registers<15> == ’1’ then
3245 LoadWritePC(MemA[address,4]);
3246
3247 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3248 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3249#endif
3250
3251 bool success = false;
3252 const uint32_t opcode = OpcodeAsUnsigned (&success);
3253 if (!success)
3254 return false;
3255
3256 if (ConditionPassed())
3257 {
3258 uint32_t n;
3259 uint32_t registers = 0;
3260 bool wback;
3261 const uint32_t addr_byte_size = GetAddressByteSize();
3262 switch (encoding)
3263 {
3264 case eEncodingA1:
3265 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3266 n = Bits32 (opcode, 19, 16);
3267 registers = Bits32 (opcode, 15, 0);
3268 wback = BitIsSet (opcode, 21);
3269
3270 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3271 if ((n == 15) || (BitCount (registers) < 1))
3272 return false;
3273
3274 break;
3275 default:
3276 return false;
3277 }
3278 // address = R[n] + 4;
3279
3280 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003281 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3282
3283 if (!success)
3284 return false;
3285
3286 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003287
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003288 EmulateInstruction::Context context;
3289 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3290 Register dwarf_reg;
3291 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3292 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003293
3294 for (int i = 0; i < 14; ++i)
3295 {
3296 if (BitIsSet (registers, i))
3297 {
3298 // R[i] = MemA[address,4]; address = address + 4;
3299
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003300 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003301 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003302 if (!success)
3303 return false;
3304
3305 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3306 return false;
3307
3308 offset += addr_byte_size;
3309 }
3310 }
3311
3312 // if registers<15> == ’1’ then
3313 // LoadWritePC(MemA[address,4]);
3314 if (BitIsSet (registers, 15))
3315 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003316 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003317 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003318 if (!success)
3319 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003320 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003321 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003322 return false;
3323 }
3324
3325 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3326 if (wback && BitIsClear (registers, n))
3327 {
Caroline Tice85aab332011-02-08 23:56:10 +00003328 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3329 if (!success)
3330 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003331
3332 offset = addr_byte_size * BitCount (registers);
3333 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003334 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003335 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003336 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3337 return false;
3338 }
3339
3340 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3341 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003342 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003343 }
3344 return true;
3345}
Caroline Tice0b29e242011-02-08 23:16:02 +00003346
Johnny Chenef21b592011-02-10 01:52:38 +00003347// Load Register (immediate) calculates an address from a base register value and
3348// an immediate offset, loads a word from memory, and writes to a register.
3349// LDR (immediate, Thumb)
3350bool
3351EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3352{
3353#if 0
3354 // ARM pseudo code...
3355 if (ConditionPassed())
3356 {
3357 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3358 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3359 address = if index then offset_addr else R[n];
3360 data = MemU[address,4];
3361 if wback then R[n] = offset_addr;
3362 if t == 15 then
3363 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3364 elsif UnalignedSupport() || address<1:0> = '00' then
3365 R[t] = data;
3366 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3367 }
3368#endif
3369
3370 bool success = false;
3371 const uint32_t opcode = OpcodeAsUnsigned (&success);
3372 if (!success)
3373 return false;
3374
3375 if (ConditionPassed())
3376 {
3377 uint32_t Rt; // the destination register
3378 uint32_t Rn; // the base register
3379 uint32_t imm32; // the immediate offset used to form the address
3380 addr_t offset_addr; // the offset address
3381 addr_t address; // the calculated address
3382 uint32_t data; // the literal data value from memory load
3383 bool add, index, wback;
3384 switch (encoding) {
3385 case eEncodingT1:
3386 Rt = Bits32(opcode, 5, 3);
3387 Rn = Bits32(opcode, 2, 0);
3388 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3389 // index = TRUE; add = TRUE; wback = FALSE
3390 add = true;
3391 index = true;
3392 wback = false;
3393 break;
3394 default:
3395 return false;
3396 }
3397 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3398 if (!success)
3399 return false;
3400 if (add)
3401 offset_addr = base + imm32;
3402 else
3403 offset_addr = base - imm32;
3404
3405 address = (index ? offset_addr : base);
3406
3407 if (wback)
3408 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003409 EmulateInstruction::Context ctx;
3410 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3411 Register dwarf_reg;
3412 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3413 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3414
Johnny Chenef21b592011-02-10 01:52:38 +00003415 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3416 return false;
3417 }
3418
3419 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003420 EmulateInstruction::Context context;
3421 context.type = EmulateInstruction::eContextImmediate;
3422 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003423
3424 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003425 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003426 if (!success)
3427 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003428
3429 if (Rt == 15)
3430 {
3431 if (Bits32(address, 1, 0) == 0)
3432 {
Johnny Chen668b4512011-02-15 21:08:58 +00003433 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003434 return false;
3435 }
3436 else
3437 return false;
3438 }
3439 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3440 {
3441 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3442 return false;
3443 }
3444 else
3445 return false;
3446 }
3447 return true;
3448}
3449
Caroline Ticeaf556562011-02-15 18:42:15 +00003450// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3451// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3452// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003453bool
3454EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3455{
3456#if 0
3457 if ConditionPassed() then
3458 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3459 address = R[n];
3460
3461 for i = 0 to 14
3462 if registers<i> == ’1’ then
3463 if i == n && wback && i != LowestSetBit(registers) then
3464 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3465 else
3466 MemA[address,4] = R[i];
3467 address = address + 4;
3468
3469 if registers<15> == ’1’ then // Only possible for encoding A1
3470 MemA[address,4] = PCStoreValue();
3471 if wback then R[n] = R[n] + 4*BitCount(registers);
3472#endif
3473
3474 bool success = false;
3475 const uint32_t opcode = OpcodeAsUnsigned (&success);
3476 if (!success)
3477 return false;
3478
3479 if (ConditionPassed ())
3480 {
3481 uint32_t n;
3482 uint32_t registers = 0;
3483 bool wback;
3484 const uint32_t addr_byte_size = GetAddressByteSize();
3485
3486 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3487 switch (encoding)
3488 {
3489 case eEncodingT1:
3490 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3491 n = Bits32 (opcode, 10, 8);
3492 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003493 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003494 wback = true;
3495
3496 // if BitCount(registers) < 1 then UNPREDICTABLE;
3497 if (BitCount (registers) < 1)
3498 return false;
3499
3500 break;
3501
3502 case eEncodingT2:
3503 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3504 n = Bits32 (opcode, 19, 16);
3505 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003506 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003507 wback = BitIsSet (opcode, 21);
3508
3509 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3510 if ((n == 15) || (BitCount (registers) < 2))
3511 return false;
3512
3513 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3514 if (wback && BitIsSet (registers, n))
3515 return false;
3516
3517 break;
3518
3519 case eEncodingA1:
3520 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3521 n = Bits32 (opcode, 19, 16);
3522 registers = Bits32 (opcode, 15, 0);
3523 wback = BitIsSet (opcode, 21);
3524
3525 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3526 if ((n == 15) || (BitCount (registers) < 1))
3527 return false;
3528
3529 break;
3530
3531 default:
3532 return false;
3533 }
3534
3535 // address = R[n];
3536 int32_t offset = 0;
3537 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3538 if (!success)
3539 return false;
3540
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003541 EmulateInstruction::Context context;
3542 context.type = EmulateInstruction::eContextRegisterStore;
3543 Register base_reg;
3544 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003545
3546 // for i = 0 to 14
3547 for (int i = 0; i < 14; ++i)
3548 {
3549 int lowest_set_bit = 14;
3550 // if registers<i> == ’1’ then
3551 if (BitIsSet (registers, i))
3552 {
3553 if (i < lowest_set_bit)
3554 lowest_set_bit = i;
3555 // if i == n && wback && i != LowestSetBit(registers) then
3556 if ((i == n) && wback && (i != lowest_set_bit))
3557 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3558 WriteBits32UnknownToMemory (address + offset);
3559 else
3560 {
3561 // MemA[address,4] = R[i];
3562 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3563 if (!success)
3564 return false;
3565
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003566 Register data_reg;
3567 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3568 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003569 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003570 return false;
3571 }
3572
3573 // address = address + 4;
3574 offset += addr_byte_size;
3575 }
3576 }
3577
3578 // if registers<15> == ’1’ then // Only possible for encoding A1
3579 // MemA[address,4] = PCStoreValue();
3580 if (BitIsSet (registers, 15))
3581 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003582 Register pc_reg;
3583 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3584 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003585 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3586 if (!success)
3587 return false;
3588
Caroline Ticecc96eb52011-02-17 19:20:40 +00003589 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003590 return false;
3591 }
3592
3593 // if wback then R[n] = R[n] + 4*BitCount(registers);
3594 if (wback)
3595 {
3596 offset = addr_byte_size * BitCount (registers);
3597 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003598 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003599 addr_t data = address + offset;
3600 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3601 return false;
3602 }
3603 }
3604 return true;
3605}
3606
Caroline Ticeaf556562011-02-15 18:42:15 +00003607// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3608// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3609// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003610bool
3611EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3612{
3613#if 0
3614 if ConditionPassed() then
3615 EncodingSpecificOperations();
3616 address = R[n] - 4*BitCount(registers) + 4;
3617
3618 for i = 0 to 14
3619 if registers<i> == ’1’ then
3620 if i == n && wback && i != LowestSetBit(registers) then
3621 MemA[address,4] = bits(32) UNKNOWN;
3622 else
3623 MemA[address,4] = R[i];
3624 address = address + 4;
3625
3626 if registers<15> == ’1’ then
3627 MemA[address,4] = PCStoreValue();
3628
3629 if wback then R[n] = R[n] - 4*BitCount(registers);
3630#endif
3631
3632 bool success = false;
3633 const uint32_t opcode = OpcodeAsUnsigned (&success);
3634 if (!success)
3635 return false;
3636
3637 if (ConditionPassed ())
3638 {
3639 uint32_t n;
3640 uint32_t registers = 0;
3641 bool wback;
3642 const uint32_t addr_byte_size = GetAddressByteSize();
3643
3644 // EncodingSpecificOperations();
3645 switch (encoding)
3646 {
3647 case eEncodingA1:
3648 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3649 n = Bits32 (opcode, 19, 16);
3650 registers = Bits32 (opcode, 15, 0);
3651 wback = BitIsSet (opcode, 21);
3652
3653 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3654 if ((n == 15) || (BitCount (registers) < 1))
3655 return false;
3656 break;
3657 default:
3658 return false;
3659 }
3660
3661 // address = R[n] - 4*BitCount(registers) + 4;
3662 int32_t offset = 0;
3663 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3664 if (!success)
3665 return false;
3666
3667 address = address - (addr_byte_size * BitCount (registers)) + 4;
3668
3669 EmulateInstruction::Context context;
3670 context.type = EmulateInstruction::eContextRegisterStore;
3671 Register base_reg;
3672 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3673
3674 // for i = 0 to 14
3675 for (int i = 0; i < 14; ++i)
3676 {
3677 int lowest_bit_set = 14;
3678 // if registers<i> == ’1’ then
3679 if (BitIsSet (registers, i))
3680 {
3681 if (i < lowest_bit_set)
3682 lowest_bit_set = i;
3683 //if i == n && wback && i != LowestSetBit(registers) then
3684 if ((i == n) && wback && (i != lowest_bit_set))
3685 // MemA[address,4] = bits(32) UNKNOWN;
3686 WriteBits32UnknownToMemory (address + offset);
3687 else
3688 {
3689 // MemA[address,4] = R[i];
3690 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3691 if (!success)
3692 return false;
3693
3694 Register data_reg;
3695 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3696 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003697 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003698 return false;
3699 }
3700
3701 // address = address + 4;
3702 offset += addr_byte_size;
3703 }
3704 }
3705
3706 // if registers<15> == ’1’ then
3707 // MemA[address,4] = PCStoreValue();
3708 if (BitIsSet (registers, 15))
3709 {
3710 Register pc_reg;
3711 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3712 context.SetRegisterPlusOffset (pc_reg, 8);
3713 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3714 if (!success)
3715 return false;
3716
Caroline Ticecc96eb52011-02-17 19:20:40 +00003717 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003718 return false;
3719 }
3720
3721 // if wback then R[n] = R[n] - 4*BitCount(registers);
3722 if (wback)
3723 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003724 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003725 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3726 context.SetImmediateSigned (offset);
3727 addr_t data = address + offset;
3728 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3729 return false;
3730 }
3731 }
3732 return true;
3733}
3734
Caroline Ticeaf556562011-02-15 18:42:15 +00003735// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3736// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3737// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003738bool
3739EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3740{
3741#if 0
3742 if ConditionPassed() then
3743 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3744 address = R[n] - 4*BitCount(registers);
3745
3746 for i = 0 to 14
3747 if registers<i> == ’1’ then
3748 if i == n && wback && i != LowestSetBit(registers) then
3749 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3750 else
3751 MemA[address,4] = R[i];
3752 address = address + 4;
3753
3754 if registers<15> == ’1’ then // Only possible for encoding A1
3755 MemA[address,4] = PCStoreValue();
3756
3757 if wback then R[n] = R[n] - 4*BitCount(registers);
3758#endif
3759
3760
3761 bool success = false;
3762 const uint32_t opcode = OpcodeAsUnsigned (&success);
3763 if (!success)
3764 return false;
3765
3766 if (ConditionPassed ())
3767 {
3768 uint32_t n;
3769 uint32_t registers = 0;
3770 bool wback;
3771 const uint32_t addr_byte_size = GetAddressByteSize();
3772
3773 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3774 switch (encoding)
3775 {
3776 case eEncodingT1:
3777 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3778 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3779 {
3780 // See PUSH
3781 }
3782 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3783 n = Bits32 (opcode, 19, 16);
3784 registers = Bits32 (opcode, 15, 0);
3785 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3786 wback = BitIsSet (opcode, 21);
3787 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3788 if ((n == 15) || BitCount (registers) < 2)
3789 return false;
3790 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3791 if (wback && BitIsSet (registers, n))
3792 return false;
3793 break;
3794
3795 case eEncodingA1:
3796 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3797 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3798 {
3799 // See Push
3800 }
3801 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3802 n = Bits32 (opcode, 19, 16);
3803 registers = Bits32 (opcode, 15, 0);
3804 wback = BitIsSet (opcode, 21);
3805 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3806 if ((n == 15) || BitCount (registers) < 1)
3807 return false;
3808 break;
3809
3810 default:
3811 return false;
3812 }
3813
3814 // address = R[n] - 4*BitCount(registers);
3815
3816 int32_t offset = 0;
3817 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3818 if (!success)
3819 return false;
3820
3821 address = address - (addr_byte_size * BitCount (registers));
3822
3823 EmulateInstruction::Context context;
3824 context.type = EmulateInstruction::eContextRegisterStore;
3825 Register base_reg;
3826 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3827
3828 // for i = 0 to 14
3829 for (int i = 0; i < 14; ++i)
3830 {
3831 uint32_t lowest_set_bit = 14;
3832 // if registers<i> == ’1’ then
3833 if (BitIsSet (registers, i))
3834 {
3835 if (i < lowest_set_bit)
3836 lowest_set_bit = i;
3837 // if i == n && wback && i != LowestSetBit(registers) then
3838 if ((i == n) && wback && (i != lowest_set_bit))
3839 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3840 WriteBits32UnknownToMemory (address + offset);
3841 else
3842 {
3843 // MemA[address,4] = R[i];
3844 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3845 if (!success)
3846 return false;
3847
3848 Register data_reg;
3849 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3850 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003851 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003852 return false;
3853 }
3854
3855 // address = address + 4;
3856 offset += addr_byte_size;
3857 }
3858 }
3859
3860 // if registers<15> == ’1’ then // Only possible for encoding A1
3861 // MemA[address,4] = PCStoreValue();
3862 if (BitIsSet (registers, 15))
3863 {
3864 Register pc_reg;
3865 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3866 context.SetRegisterPlusOffset (pc_reg, 8);
3867 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3868 if (!success)
3869 return false;
3870
Caroline Ticecc96eb52011-02-17 19:20:40 +00003871 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003872 return false;
3873 }
3874
3875 // if wback then R[n] = R[n] - 4*BitCount(registers);
3876 if (wback)
3877 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003878 offset = (addr_byte_size * BitCount (registers)) * -1;
3879 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3880 context.SetImmediateSigned (offset);
3881 addr_t data = address + offset;
3882 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3883 return false;
3884 }
3885 }
3886 return true;
3887}
3888
3889// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3890// from a base register. The consecutive memory locations start just above this address, and the address of the last
3891// of those locations can optionally be written back to the base register.
3892bool
3893EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3894{
3895#if 0
3896 if ConditionPassed() then
3897 EncodingSpecificOperations();
3898 address = R[n] + 4;
3899
3900 for i = 0 to 14
3901 if registers<i> == ’1’ then
3902 if i == n && wback && i != LowestSetBit(registers) then
3903 MemA[address,4] = bits(32) UNKNOWN;
3904 else
3905 MemA[address,4] = R[i];
3906 address = address + 4;
3907
3908 if registers<15> == ’1’ then
3909 MemA[address,4] = PCStoreValue();
3910
3911 if wback then R[n] = R[n] + 4*BitCount(registers);
3912#endif
3913
3914 bool success = false;
3915 const uint32_t opcode = OpcodeAsUnsigned (&success);
3916 if (!success)
3917 return false;
3918
3919 if (ConditionPassed())
3920 {
3921 uint32_t n;
3922 uint32_t registers = 0;
3923 bool wback;
3924 const uint32_t addr_byte_size = GetAddressByteSize();
3925
3926 // EncodingSpecificOperations();
3927 switch (encoding)
3928 {
3929 case eEncodingA1:
3930 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3931 n = Bits32 (opcode, 19, 16);
3932 registers = Bits32 (opcode, 15, 0);
3933 wback = BitIsSet (opcode, 21);
3934
3935 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3936 if ((n == 15) && (BitCount (registers) < 1))
3937 return false;
3938 break;
3939 default:
3940 return false;
3941 }
3942 // address = R[n] + 4;
3943
3944 int32_t offset = 0;
3945 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3946 if (!success)
3947 return false;
3948
3949 address = address + addr_byte_size;
3950
3951 EmulateInstruction::Context context;
3952 context.type = EmulateInstruction::eContextRegisterStore;
3953 Register base_reg;
3954 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3955
3956 uint32_t lowest_set_bit = 14;
3957 // for i = 0 to 14
3958 for (int i = 0; i < 14; ++i)
3959 {
3960 // if registers<i> == ’1’ then
3961 if (BitIsSet (registers, i))
3962 {
3963 if (i < lowest_set_bit)
3964 lowest_set_bit = i;
3965 // if i == n && wback && i != LowestSetBit(registers) then
3966 if ((i == n) && wback && (i != lowest_set_bit))
3967 // MemA[address,4] = bits(32) UNKNOWN;
3968 WriteBits32UnknownToMemory (address + offset);
3969 // else
3970 else
3971 {
3972 // MemA[address,4] = R[i];
3973 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3974 if (!success)
3975 return false;
3976
3977 Register data_reg;
3978 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3979 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003980 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003981 return false;
3982 }
3983
3984 // address = address + 4;
3985 offset += addr_byte_size;
3986 }
3987 }
3988
3989 // if registers<15> == ’1’ then
3990 // MemA[address,4] = PCStoreValue();
3991 if (BitIsSet (registers, 15))
3992 {
3993 Register pc_reg;
3994 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3995 context.SetRegisterPlusOffset (pc_reg, 8);
3996 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3997 if (!success)
3998 return false;
3999
Caroline Ticecc96eb52011-02-17 19:20:40 +00004000 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004001 return false;
4002 }
4003
4004 // if wback then R[n] = R[n] + 4*BitCount(registers);
4005 if (wback)
4006 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004007 offset = addr_byte_size * BitCount (registers);
4008 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4009 context.SetImmediateSigned (offset);
4010 addr_t data = address + offset;
4011 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4012 return false;
4013 }
4014 }
4015 return true;
4016}
Caroline Tice7fac8572011-02-15 22:53:54 +00004017
4018// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4019// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4020bool
4021EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4022{
4023#if 0
4024 if ConditionPassed() then
4025 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4026 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4027 address = if index then offset_addr else R[n];
4028 if UnalignedSupport() || address<1:0> == ’00’ then
4029 MemU[address,4] = R[t];
4030 else // Can only occur before ARMv7
4031 MemU[address,4] = bits(32) UNKNOWN;
4032 if wback then R[n] = offset_addr;
4033#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004034
Caroline Tice7fac8572011-02-15 22:53:54 +00004035 bool success = false;
4036 const uint32_t opcode = OpcodeAsUnsigned (&success);
4037 if (!success)
4038 return false;
4039
4040 if (ConditionPassed())
4041 {
4042 const uint32_t addr_byte_size = GetAddressByteSize();
4043
4044 uint32_t t;
4045 uint32_t n;
4046 uint32_t imm32;
4047 bool index;
4048 bool add;
4049 bool wback;
4050 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4051 switch (encoding)
4052 {
4053 case eEncodingT1:
4054 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4055 t = Bits32 (opcode, 2, 0);
4056 n = Bits32 (opcode, 5, 3);
4057 imm32 = Bits32 (opcode, 10, 6) << 2;
4058
4059 // index = TRUE; add = TRUE; wback = FALSE;
4060 index = true;
4061 add = false;
4062 wback = false;
4063 break;
4064
4065 case eEncodingT2:
4066 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4067 t = Bits32 (opcode, 10, 8);
4068 n = 13;
4069 imm32 = Bits32 (opcode, 7, 0) << 2;
4070
4071 // index = TRUE; add = TRUE; wback = FALSE;
4072 index = true;
4073 add = true;
4074 wback = false;
4075 break;
4076
4077 case eEncodingT3:
4078 // if Rn == ’1111’ then UNDEFINED;
4079 if (Bits32 (opcode, 19, 16) == 15)
4080 return false;
4081
4082 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4083 t = Bits32 (opcode, 15, 12);
4084 n = Bits32 (opcode, 19, 16);
4085 imm32 = Bits32 (opcode, 11, 0);
4086
4087 // index = TRUE; add = TRUE; wback = FALSE;
4088 index = true;
4089 add = true;
4090 wback = false;
4091
4092 // if t == 15 then UNPREDICTABLE;
4093 if (t == 15)
4094 return false;
4095 break;
4096
4097 case eEncodingT4:
4098 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4099 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4100 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4101 if ((Bits32 (opcode, 19, 16) == 15)
4102 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4103 return false;
4104
4105 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4106 t = Bits32 (opcode, 15, 12);
4107 n = Bits32 (opcode, 19, 16);
4108 imm32 = Bits32 (opcode, 7, 0);
4109
4110 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4111 index = BitIsSet (opcode, 10);
4112 add = BitIsSet (opcode, 9);
4113 wback = BitIsSet (opcode, 8);
4114
4115 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4116 if ((t == 15) || (wback && (n == t)))
4117 return false;
4118 break;
4119
4120 default:
4121 return false;
4122 }
4123
4124 addr_t offset_addr;
4125 addr_t address;
4126
4127 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4128 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4129 if (!success)
4130 return false;
4131
4132 if (add)
4133 offset_addr = base_address + imm32;
4134 else
4135 offset_addr = base_address - imm32;
4136
4137 // address = if index then offset_addr else R[n];
4138 if (index)
4139 address = offset_addr;
4140 else
4141 address = base_address;
4142
4143 EmulateInstruction::Context context;
4144 context.type = eContextRegisterStore;
4145 Register base_reg;
4146 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4147
4148 // if UnalignedSupport() || address<1:0> == ’00’ then
4149 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4150 {
4151 // MemU[address,4] = R[t];
4152 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4153 if (!success)
4154 return false;
4155
4156 Register data_reg;
4157 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4158 int32_t offset = address - base_address;
4159 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004160 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004161 return false;
4162 }
4163 else
4164 {
4165 // MemU[address,4] = bits(32) UNKNOWN;
4166 WriteBits32UnknownToMemory (address);
4167 }
4168
4169 // if wback then R[n] = offset_addr;
4170 if (wback)
4171 {
4172 context.type = eContextRegisterLoad;
4173 context.SetAddress (offset_addr);
4174 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4175 return false;
4176 }
4177 }
4178 return true;
4179}
Caroline Ticeaf556562011-02-15 18:42:15 +00004180
Caroline Tice3fd63e92011-02-16 00:33:43 +00004181// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4182// word from a register to memory. The offset register value can optionally be shifted.
4183bool
4184EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4185{
4186#if 0
4187 if ConditionPassed() then
4188 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4189 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4190 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4191 address = if index then offset_addr else R[n];
4192 if t == 15 then // Only possible for encoding A1
4193 data = PCStoreValue();
4194 else
4195 data = R[t];
4196 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4197 MemU[address,4] = data;
4198 else // Can only occur before ARMv7
4199 MemU[address,4] = bits(32) UNKNOWN;
4200 if wback then R[n] = offset_addr;
4201#endif
4202
4203 bool success = false;
4204 const uint32_t opcode = OpcodeAsUnsigned (&success);
4205 if (!success)
4206 return false;
4207
4208 if (ConditionPassed())
4209 {
4210 const uint32_t addr_byte_size = GetAddressByteSize();
4211
4212 uint32_t t;
4213 uint32_t n;
4214 uint32_t m;
4215 ARM_ShifterType shift_t;
4216 uint32_t shift_n;
4217 bool index;
4218 bool add;
4219 bool wback;
4220
4221 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4222 switch (encoding)
4223 {
4224 case eEncodingT1:
4225 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4226 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4227 t = Bits32 (opcode, 2, 0);
4228 n = Bits32 (opcode, 5, 3);
4229 m = Bits32 (opcode, 8, 6);
4230
4231 // index = TRUE; add = TRUE; wback = FALSE;
4232 index = true;
4233 add = true;
4234 wback = false;
4235
4236 // (shift_t, shift_n) = (SRType_LSL, 0);
4237 shift_t = SRType_LSL;
4238 shift_n = 0;
4239 break;
4240
4241 case eEncodingT2:
4242 // if Rn == ’1111’ then UNDEFINED;
4243 if (Bits32 (opcode, 19, 16) == 15)
4244 return false;
4245
4246 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4247 t = Bits32 (opcode, 15, 12);
4248 n = Bits32 (opcode, 19, 16);
4249 m = Bits32 (opcode, 3, 0);
4250
4251 // index = TRUE; add = TRUE; wback = FALSE;
4252 index = true;
4253 add = true;
4254 wback = false;
4255
4256 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4257 shift_t = SRType_LSL;
4258 shift_n = Bits32 (opcode, 5, 4);
4259
4260 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4261 if ((t == 15) || (BadReg (m)))
4262 return false;
4263 break;
4264
4265 case eEncodingA1:
4266 {
4267 // if P == ’0’ && W == ’1’ then SEE STRT;
4268 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4269 t = Bits32 (opcode, 15, 12);
4270 n = Bits32 (opcode, 19, 16);
4271 m = Bits32 (opcode, 3, 0);
4272
4273 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4274 index = BitIsSet (opcode, 24);
4275 add = BitIsSet (opcode, 23);
4276 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4277
4278 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4279 uint32_t typ = Bits32 (opcode, 6, 5);
4280 uint32_t imm5 = Bits32 (opcode, 11, 7);
4281 shift_n = DecodeImmShift(typ, imm5, shift_t);
4282
4283 // if m == 15 then UNPREDICTABLE;
4284 if (m == 15)
4285 return false;
4286
4287 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4288 if (wback && ((n == 15) || (n == t)))
4289 return false;
4290
4291 break;
4292 }
4293 default:
4294 return false;
4295 }
4296
4297 addr_t offset_addr;
4298 addr_t address;
4299 int32_t offset = 0;
4300
4301 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4302 if (!success)
4303 return false;
4304
4305 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4306 if (!success)
4307 return false;
4308
4309 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004310 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004311
4312 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4313 if (add)
4314 offset_addr = base_address + offset;
4315 else
4316 offset_addr = base_address - offset;
4317
4318 // address = if index then offset_addr else R[n];
4319 if (index)
4320 address = offset_addr;
4321 else
4322 address = base_address;
4323
4324 uint32_t data;
4325 // if t == 15 then // Only possible for encoding A1
4326 if (t == 15)
4327 // data = PCStoreValue();
4328 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4329 else
4330 // data = R[t];
4331 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4332
4333 if (!success)
4334 return false;
4335
4336 EmulateInstruction::Context context;
4337 context.type = eContextRegisterStore;
4338
4339 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4340 if (UnalignedSupport ()
4341 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4342 || CurrentInstrSet() == eModeARM)
4343 {
4344 // MemU[address,4] = data;
4345
4346 Register base_reg;
4347 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4348
4349 Register data_reg;
4350 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4351
4352 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004353 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004354 return false;
4355
4356 }
4357 else
4358 // MemU[address,4] = bits(32) UNKNOWN;
4359 WriteBits32UnknownToMemory (address);
4360
4361 // if wback then R[n] = offset_addr;
4362 if (wback)
4363 {
4364 context.type = eContextRegisterLoad;
4365 context.SetAddress (offset_addr);
4366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4367 return false;
4368 }
4369
4370 }
4371 return true;
4372}
Caroline Tice73a29de2011-02-16 20:22:22 +00004373
4374bool
4375EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4376{
4377#if 0
4378 if ConditionPassed() then
4379 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4380 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4381 address = if index then offset_addr else R[n];
4382 MemU[address,1] = R[t]<7:0>;
4383 if wback then R[n] = offset_addr;
4384#endif
4385
4386
4387 bool success = false;
4388 const uint32_t opcode = OpcodeAsUnsigned (&success);
4389 if (!success)
4390 return false;
4391
4392 if (ConditionPassed ())
4393 {
4394 uint32_t t;
4395 uint32_t n;
4396 uint32_t imm32;
4397 bool index;
4398 bool add;
4399 bool wback;
4400 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4401 switch (encoding)
4402 {
4403 case eEncodingT1:
4404 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4405 t = Bits32 (opcode, 2, 0);
4406 n = Bits32 (opcode, 5, 3);
4407 imm32 = Bits32 (opcode, 10, 6);
4408
4409 // index = TRUE; add = TRUE; wback = FALSE;
4410 index = true;
4411 add = true;
4412 wback = false;
4413 break;
4414
4415 case eEncodingT2:
4416 // if Rn == ’1111’ then UNDEFINED;
4417 if (Bits32 (opcode, 19, 16) == 15)
4418 return false;
4419
4420 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4421 t = Bits32 (opcode, 15, 12);
4422 n = Bits32 (opcode, 19, 16);
4423 imm32 = Bits32 (opcode, 11, 0);
4424
4425 // index = TRUE; add = TRUE; wback = FALSE;
4426 index = true;
4427 add = true;
4428 wback = false;
4429
4430 // if BadReg(t) then UNPREDICTABLE;
4431 if (BadReg (t))
4432 return false;
4433 break;
4434
4435 case eEncodingT3:
4436 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4437 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4438 if (Bits32 (opcode, 19, 16) == 15)
4439 return false;
4440
4441 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4442 t = Bits32 (opcode, 15, 12);
4443 n = Bits32 (opcode, 19, 16);
4444 imm32 = Bits32 (opcode, 7, 0);
4445
4446 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4447 index = BitIsSet (opcode, 10);
4448 add = BitIsSet (opcode, 9);
4449 wback = BitIsSet (opcode, 8);
4450
4451 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4452 if ((BadReg (t)) || (wback && (n == t)))
4453 return false;
4454 break;
4455
4456 default:
4457 return false;
4458 }
4459
4460 addr_t offset_addr;
4461 addr_t address;
4462 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4463 if (!success)
4464 return false;
4465
4466 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4467 if (add)
4468 offset_addr = base_address + imm32;
4469 else
4470 offset_addr = base_address - imm32;
4471
4472 // address = if index then offset_addr else R[n];
4473 if (index)
4474 address = offset_addr;
4475 else
4476 address = base_address;
4477
Caroline Ticecc96eb52011-02-17 19:20:40 +00004478 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004479 Register base_reg;
4480 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4481
4482 Register data_reg;
4483 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4484
4485 EmulateInstruction::Context context;
4486 context.type = eContextRegisterStore;
4487 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4488
4489 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4490 if (!success)
4491 return false;
4492
4493 data = Bits32 (data, 7, 0);
4494
Caroline Ticecc96eb52011-02-17 19:20:40 +00004495 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004496 return false;
4497
4498 // if wback then R[n] = offset_addr;
4499 if (wback)
4500 {
4501 context.type = eContextRegisterLoad;
4502 context.SetAddress (offset_addr);
4503 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4504 return false;
4505 }
4506
4507 }
4508
4509 return true;
4510}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004511
Johnny Chen157b9592011-02-18 21:13:05 +00004512// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4513// and writes the result to the destination register. It can optionally update the condition flags
4514// based on the result.
4515bool
4516EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4517{
4518#if 0
4519 // ARM pseudo code...
4520 if ConditionPassed() then
4521 EncodingSpecificOperations();
4522 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4523 if d == 15 then // Can only occur for ARM encoding
4524 ALUWritePC(result); // setflags is always FALSE here
4525 else
4526 R[d] = result;
4527 if setflags then
4528 APSR.N = result<31>;
4529 APSR.Z = IsZeroBit(result);
4530 APSR.C = carry;
4531 APSR.V = overflow;
4532#endif
4533
4534 bool success = false;
4535 const uint32_t opcode = OpcodeAsUnsigned (&success);
4536 if (!success)
4537 return false;
4538
4539 if (ConditionPassed())
4540 {
4541 uint32_t Rd, Rn;
4542 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4543 bool setflags;
4544 switch (encoding)
4545 {
4546 case eEncodingT1:
4547 Rd = Bits32(opcode, 11, 8);
4548 Rn = Bits32(opcode, 19, 16);
4549 setflags = BitIsSet(opcode, 20);
4550 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4551 if (BadReg(Rd) || BadReg(Rn))
4552 return false;
4553 break;
4554 case eEncodingA1:
4555 Rd = Bits32(opcode, 15, 12);
4556 Rn = Bits32(opcode, 19, 16);
4557 setflags = BitIsSet(opcode, 20);
4558 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4559 // TODO: Emulate SUBS PC, LR and related instructions.
4560 if (Rd == 15 && setflags)
4561 return false;
4562 break;
4563 default:
4564 return false;
4565 }
4566
4567 // Read the first operand.
4568 int32_t val1 = ReadCoreReg(Rn, &success);
4569 if (!success)
4570 return false;
4571
4572 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4573
4574 EmulateInstruction::Context context;
4575 context.type = EmulateInstruction::eContextImmediate;
4576 context.SetNoArgs ();
4577
4578 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4579 return false;
4580 }
4581 return true;
4582}
4583
4584// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4585// register value, and writes the result to the destination register. It can optionally update the
4586// condition flags based on the result.
4587bool
4588EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4589{
4590#if 0
4591 // ARM pseudo code...
4592 if ConditionPassed() then
4593 EncodingSpecificOperations();
4594 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4595 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4596 if d == 15 then // Can only occur for ARM encoding
4597 ALUWritePC(result); // setflags is always FALSE here
4598 else
4599 R[d] = result;
4600 if setflags then
4601 APSR.N = result<31>;
4602 APSR.Z = IsZeroBit(result);
4603 APSR.C = carry;
4604 APSR.V = overflow;
4605#endif
4606
4607 bool success = false;
4608 const uint32_t opcode = OpcodeAsUnsigned (&success);
4609 if (!success)
4610 return false;
4611
4612 if (ConditionPassed())
4613 {
4614 uint32_t Rd, Rn, Rm;
4615 ARM_ShifterType shift_t;
4616 uint32_t shift_n; // the shift applied to the value read from Rm
4617 bool setflags;
4618 switch (encoding)
4619 {
4620 case eEncodingT1:
4621 Rd = Rn = Bits32(opcode, 2, 0);
4622 Rm = Bits32(opcode, 5, 3);
4623 setflags = !InITBlock();
4624 shift_t = SRType_LSL;
4625 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004626 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004627 case eEncodingT2:
4628 Rd = Bits32(opcode, 11, 8);
4629 Rn = Bits32(opcode, 19, 16);
4630 Rm = Bits32(opcode, 3, 0);
4631 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004632 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004633 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4634 return false;
4635 break;
4636 case eEncodingA1:
4637 Rd = Bits32(opcode, 15, 12);
4638 Rn = Bits32(opcode, 19, 16);
4639 Rm = Bits32(opcode, 3, 0);
4640 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004641 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004642 // TODO: Emulate SUBS PC, LR and related instructions.
4643 if (Rd == 15 && setflags)
4644 return false;
4645 break;
4646 default:
4647 return false;
4648 }
4649
4650 // Read the first operand.
4651 int32_t val1 = ReadCoreReg(Rn, &success);
4652 if (!success)
4653 return false;
4654
4655 // Read the second operand.
4656 int32_t val2 = ReadCoreReg(Rm, &success);
4657 if (!success)
4658 return false;
4659
4660 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4661 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4662
4663 EmulateInstruction::Context context;
4664 context.type = EmulateInstruction::eContextImmediate;
4665 context.SetNoArgs ();
4666
4667 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4668 return false;
4669 }
4670 return true;
4671}
4672
Johnny Chena695f952011-02-23 21:24:25 +00004673// This instruction adds an immediate value to the PC value to form a PC-relative address,
4674// and writes the result to the destination register.
4675bool
4676EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4677{
4678#if 0
4679 // ARM pseudo code...
4680 if ConditionPassed() then
4681 EncodingSpecificOperations();
4682 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
4683 if d == 15 then // Can only occur for ARM encodings
4684 ALUWritePC(result);
4685 else
4686 R[d] = result;
4687#endif
4688
4689 bool success = false;
4690 const uint32_t opcode = OpcodeAsUnsigned (&success);
4691 if (!success)
4692 return false;
4693
4694 if (ConditionPassed())
4695 {
4696 uint32_t Rd;
4697 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
4698 bool add;
4699 switch (encoding)
4700 {
4701 case eEncodingT1:
4702 Rd = Bits32(opcode, 10, 8);
4703 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
4704 break;
4705 case eEncodingT2:
4706 case eEncodingT3:
4707 Rd = Bits32(opcode, 11, 8);
4708 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
4709 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
4710 if (BadReg(Rd))
4711 return false;
4712 break;
4713 case eEncodingA1:
4714 case eEncodingA2:
4715 Rd = Bits32(opcode, 15, 12);
4716 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4717 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
4718 break;
4719 default:
4720 return false;
4721 }
4722
4723 // Read the PC value.
4724 uint32_t pc = ReadCoreReg(PC_REG, &success);
4725 if (!success)
4726 return false;
4727
4728 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
4729
4730 EmulateInstruction::Context context;
4731 context.type = EmulateInstruction::eContextImmediate;
4732 context.SetNoArgs ();
4733
4734 if (!WriteCoreReg(context, result, Rd))
4735 return false;
4736 }
4737 return true;
4738}
4739
Johnny Chene97c0d52011-02-18 19:32:20 +00004740// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4741// to the destination register. It can optionally update the condition flags based on the result.
4742bool
4743EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4744{
4745#if 0
4746 // ARM pseudo code...
4747 if ConditionPassed() then
4748 EncodingSpecificOperations();
4749 result = R[n] AND imm32;
4750 if d == 15 then // Can only occur for ARM encoding
4751 ALUWritePC(result); // setflags is always FALSE here
4752 else
4753 R[d] = result;
4754 if setflags then
4755 APSR.N = result<31>;
4756 APSR.Z = IsZeroBit(result);
4757 APSR.C = carry;
4758 // APSR.V unchanged
4759#endif
4760
4761 bool success = false;
4762 const uint32_t opcode = OpcodeAsUnsigned (&success);
4763 if (!success)
4764 return false;
4765
4766 if (ConditionPassed())
4767 {
4768 uint32_t Rd, Rn;
4769 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4770 bool setflags;
4771 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4772 switch (encoding)
4773 {
4774 case eEncodingT1:
4775 Rd = Bits32(opcode, 11, 8);
4776 Rn = Bits32(opcode, 19, 16);
4777 setflags = BitIsSet(opcode, 20);
4778 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004779 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004780 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004781 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004782 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4783 return false;
4784 break;
4785 case eEncodingA1:
4786 Rd = Bits32(opcode, 15, 12);
4787 Rn = Bits32(opcode, 19, 16);
4788 setflags = BitIsSet(opcode, 20);
4789 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4790 // TODO: Emulate SUBS PC, LR and related instructions.
4791 if (Rd == 15 && setflags)
4792 return false;
4793 break;
4794 default:
4795 return false;
4796 }
4797
Johnny Chene97c0d52011-02-18 19:32:20 +00004798 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004799 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004800 if (!success)
4801 return false;
4802
4803 uint32_t result = val1 & imm32;
4804
4805 EmulateInstruction::Context context;
4806 context.type = EmulateInstruction::eContextImmediate;
4807 context.SetNoArgs ();
4808
4809 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4810 return false;
4811 }
4812 return true;
4813}
4814
4815// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4816// and writes the result to the destination register. It can optionally update the condition flags
4817// based on the result.
4818bool
4819EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4820{
4821#if 0
4822 // ARM pseudo code...
4823 if ConditionPassed() then
4824 EncodingSpecificOperations();
4825 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4826 result = R[n] AND shifted;
4827 if d == 15 then // Can only occur for ARM encoding
4828 ALUWritePC(result); // setflags is always FALSE here
4829 else
4830 R[d] = result;
4831 if setflags then
4832 APSR.N = result<31>;
4833 APSR.Z = IsZeroBit(result);
4834 APSR.C = carry;
4835 // APSR.V unchanged
4836#endif
4837
4838 bool success = false;
4839 const uint32_t opcode = OpcodeAsUnsigned (&success);
4840 if (!success)
4841 return false;
4842
4843 if (ConditionPassed())
4844 {
4845 uint32_t Rd, Rn, Rm;
4846 ARM_ShifterType shift_t;
4847 uint32_t shift_n; // the shift applied to the value read from Rm
4848 bool setflags;
4849 uint32_t carry;
4850 switch (encoding)
4851 {
4852 case eEncodingT1:
4853 Rd = Rn = Bits32(opcode, 2, 0);
4854 Rm = Bits32(opcode, 5, 3);
4855 setflags = !InITBlock();
4856 shift_t = SRType_LSL;
4857 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004858 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004859 case eEncodingT2:
4860 Rd = Bits32(opcode, 11, 8);
4861 Rn = Bits32(opcode, 19, 16);
4862 Rm = Bits32(opcode, 3, 0);
4863 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004864 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004865 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004866 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004867 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004868 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4869 return false;
4870 break;
4871 case eEncodingA1:
4872 Rd = Bits32(opcode, 15, 12);
4873 Rn = Bits32(opcode, 19, 16);
4874 Rm = Bits32(opcode, 3, 0);
4875 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004876 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004877 // TODO: Emulate SUBS PC, LR and related instructions.
4878 if (Rd == 15 && setflags)
4879 return false;
4880 break;
4881 default:
4882 return false;
4883 }
4884
Johnny Chene97c0d52011-02-18 19:32:20 +00004885 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004886 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004887 if (!success)
4888 return false;
4889
4890 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004891 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004892 if (!success)
4893 return false;
4894
4895 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4896 uint32_t result = val1 & shifted;
4897
4898 EmulateInstruction::Context context;
4899 context.type = EmulateInstruction::eContextImmediate;
4900 context.SetNoArgs ();
4901
4902 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4903 return false;
4904 }
4905 return true;
4906}
4907
Caroline Tice4d729c52011-02-18 00:55:53 +00004908// 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 +00004909// 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 +00004910bool
4911EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4912{
4913#if 0
4914 if ConditionPassed() then
4915 EncodingSpecificOperations();
4916 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4917 address = if index then offset_addr else R[n];
4918 data = MemU[address,4];
4919 if wback then R[n] = offset_addr;
4920 if t == 15 then
4921 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4922 elsif UnalignedSupport() || address<1:0> = ’00’ then
4923 R[t] = data;
4924 else // Can only apply before ARMv7
4925 R[t] = ROR(data, 8*UInt(address<1:0>));
4926#endif
4927
4928 bool success = false;
4929 const uint32_t opcode = OpcodeAsUnsigned (&success);
4930 if (!success)
4931 return false;
4932
4933 if (ConditionPassed ())
4934 {
4935 const uint32_t addr_byte_size = GetAddressByteSize();
4936
4937 uint32_t t;
4938 uint32_t n;
4939 uint32_t imm32;
4940 bool index;
4941 bool add;
4942 bool wback;
4943
4944 switch (encoding)
4945 {
4946 case eEncodingA1:
4947 // if Rn == ’1111’ then SEE LDR (literal);
4948 // if P == ’0’ && W == ’1’ then SEE LDRT;
4949 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4950 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4951 t = Bits32 (opcode, 15, 12);
4952 n = Bits32 (opcode, 19, 16);
4953 imm32 = Bits32 (opcode, 11, 0);
4954
4955 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4956 index = BitIsSet (opcode, 24);
4957 add = BitIsSet (opcode, 23);
4958 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4959
4960 // if wback && n == t then UNPREDICTABLE;
4961 if (wback && (n == t))
4962 return false;
4963
4964 break;
4965
4966 default:
4967 return false;
4968 }
4969
4970 addr_t address;
4971 addr_t offset_addr;
4972 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4973 if (!success)
4974 return false;
4975
4976 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4977 if (add)
4978 offset_addr = base_address + imm32;
4979 else
4980 offset_addr = base_address - imm32;
4981
4982 // address = if index then offset_addr else R[n];
4983 if (index)
4984 address = offset_addr;
4985 else
4986 address = base_address;
4987
4988 // data = MemU[address,4];
4989
4990 Register base_reg;
4991 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4992
4993 EmulateInstruction::Context context;
4994 context.type = eContextRegisterLoad;
4995 context.SetRegisterPlusOffset (base_reg, address - base_address);
4996
4997 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4998 if (!success)
4999 return false;
5000
5001 // if wback then R[n] = offset_addr;
5002 if (wback)
5003 {
5004 context.type = eContextAdjustBaseRegister;
5005 context.SetAddress (offset_addr);
5006 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5007 return false;
5008 }
5009
5010 // if t == 15 then
5011 if (t == 15)
5012 {
5013 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5014 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5015 {
5016 // LoadWritePC (data);
5017 context.type = eContextRegisterLoad;
5018 context.SetRegisterPlusOffset (base_reg, address - base_address);
5019 LoadWritePC (context, data);
5020 }
5021 else
5022 return false;
5023 }
5024 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5025 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5026 {
5027 // R[t] = data;
5028 context.type = eContextRegisterLoad;
5029 context.SetRegisterPlusOffset (base_reg, address - base_address);
5030 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5031 return false;
5032 }
5033 // else // Can only apply before ARMv7
5034 else
5035 {
5036 // R[t] = ROR(data, 8*UInt(address<1:0>));
5037 data = ROR (data, Bits32 (address, 1, 0));
5038 context.type = eContextRegisterLoad;
5039 context.SetImmediate (data);
5040 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5041 return false;
5042 }
5043
5044 }
5045 return true;
5046}
5047
Caroline Ticefe479112011-02-18 18:52:37 +00005048// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5049// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5050bool
5051EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5052{
5053#if 0
5054 if ConditionPassed() then
5055 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5056 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5057 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5058 address = if index then offset_addr else R[n];
5059 data = MemU[address,4];
5060 if wback then R[n] = offset_addr;
5061 if t == 15 then
5062 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5063 elsif UnalignedSupport() || address<1:0> = ’00’ then
5064 R[t] = data;
5065 else // Can only apply before ARMv7
5066 if CurrentInstrSet() == InstrSet_ARM then
5067 R[t] = ROR(data, 8*UInt(address<1:0>));
5068 else
5069 R[t] = bits(32) UNKNOWN;
5070#endif
5071
5072 bool success = false;
5073 const uint32_t opcode = OpcodeAsUnsigned (&success);
5074 if (!success)
5075 return false;
5076
5077 if (ConditionPassed ())
5078 {
5079 const uint32_t addr_byte_size = GetAddressByteSize();
5080
5081 uint32_t t;
5082 uint32_t n;
5083 uint32_t m;
5084 bool index;
5085 bool add;
5086 bool wback;
5087 ARM_ShifterType shift_t;
5088 uint32_t shift_n;
5089
5090 switch (encoding)
5091 {
5092 case eEncodingT1:
5093 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5094 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5095 t = Bits32 (opcode, 2, 0);
5096 n = Bits32 (opcode, 5, 3);
5097 m = Bits32 (opcode, 8, 6);
5098
5099 // index = TRUE; add = TRUE; wback = FALSE;
5100 index = true;
5101 add = true;
5102 wback = false;
5103
5104 // (shift_t, shift_n) = (SRType_LSL, 0);
5105 shift_t = SRType_LSL;
5106 shift_n = 0;
5107
5108 break;
5109
5110 case eEncodingT2:
5111 // if Rn == ’1111’ then SEE LDR (literal);
5112 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5113 t = Bits32 (opcode, 15, 12);
5114 n = Bits32 (opcode, 19, 16);
5115 m = Bits32 (opcode, 3, 0);
5116
5117 // index = TRUE; add = TRUE; wback = FALSE;
5118 index = true;
5119 add = true;
5120 wback = false;
5121
5122 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5123 shift_t = SRType_LSL;
5124 shift_n = Bits32 (opcode, 5, 4);
5125
5126 // if BadReg(m) then UNPREDICTABLE;
5127 if (BadReg (m))
5128 return false;
5129
5130 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5131 if ((t == 15) && InITBlock() && !LastInITBlock())
5132 return false;
5133
5134 break;
5135
5136 case eEncodingA1:
5137 {
5138 // if P == ’0’ && W == ’1’ then SEE LDRT;
5139 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5140 t = Bits32 (opcode, 15, 12);
5141 n = Bits32 (opcode, 19, 16);
5142 m = Bits32 (opcode, 3, 0);
5143
5144 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5145 index = BitIsSet (opcode, 24);
5146 add = BitIsSet (opcode, 23);
5147 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5148
5149 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5150 uint32_t type = Bits32 (opcode, 6, 5);
5151 uint32_t imm5 = Bits32 (opcode, 11, 7);
5152 shift_n = DecodeImmShift (type, imm5, shift_t);
5153
5154 // if m == 15 then UNPREDICTABLE;
5155 if (m == 15)
5156 return false;
5157
5158 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5159 if (wback && ((n == 15) || (n == t)))
5160 return false;
5161 }
5162 break;
5163
5164
5165 default:
5166 return false;
5167 }
5168
5169 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5170 if (!success)
5171 return false;
5172
5173 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5174 if (!success)
5175 return false;
5176
5177 addr_t offset_addr;
5178 addr_t address;
5179
5180 // 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 +00005181 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005182
5183 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5184 if (add)
5185 offset_addr = Rn + offset;
5186 else
5187 offset_addr = Rn - offset;
5188
5189 // address = if index then offset_addr else R[n];
5190 if (index)
5191 address = offset_addr;
5192 else
5193 address = Rn;
5194
5195 // data = MemU[address,4];
5196 Register base_reg;
5197 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5198
5199 EmulateInstruction::Context context;
5200 context.type = eContextRegisterLoad;
5201 context.SetRegisterPlusOffset (base_reg, address - Rn);
5202
5203 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5204 if (!success)
5205 return false;
5206
5207 // if wback then R[n] = offset_addr;
5208 if (wback)
5209 {
5210 context.type = eContextAdjustBaseRegister;
5211 context.SetAddress (offset_addr);
5212 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5213 return false;
5214 }
5215
5216 // if t == 15 then
5217 if (t == 15)
5218 {
5219 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5220 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5221 {
5222 context.type = eContextRegisterLoad;
5223 context.SetRegisterPlusOffset (base_reg, address - Rn);
5224 LoadWritePC (context, data);
5225 }
5226 else
5227 return false;
5228 }
5229 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5230 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5231 {
5232 // R[t] = data;
5233 context.type = eContextRegisterLoad;
5234 context.SetRegisterPlusOffset (base_reg, address - Rn);
5235 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5236 return false;
5237 }
5238 else // Can only apply before ARMv7
5239 {
5240 // if CurrentInstrSet() == InstrSet_ARM then
5241 if (CurrentInstrSet () == eModeARM)
5242 {
5243 // R[t] = ROR(data, 8*UInt(address<1:0>));
5244 data = ROR (data, Bits32 (address, 1, 0));
5245 context.type = eContextRegisterLoad;
5246 context.SetImmediate (data);
5247 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5248 return false;
5249 }
5250 else
5251 {
5252 // R[t] = bits(32) UNKNOWN;
5253 WriteBits32Unknown (t);
5254 }
5255 }
5256 }
5257 return true;
5258}
Caroline Tice21b604b2011-02-18 21:06:04 +00005259
5260// LDRB (immediate, Thumb)
5261bool
5262EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5263{
5264#if 0
5265 if ConditionPassed() then
5266 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5267 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5268 address = if index then offset_addr else R[n];
5269 R[t] = ZeroExtend(MemU[address,1], 32);
5270 if wback then R[n] = offset_addr;
5271#endif
5272
5273 bool success = false;
5274 const uint32_t opcode = OpcodeAsUnsigned (&success);
5275 if (!success)
5276 return false;
5277
5278 if (ConditionPassed ())
5279 {
5280 uint32_t t;
5281 uint32_t n;
5282 uint32_t imm32;
5283 bool index;
5284 bool add;
5285 bool wback;
5286
5287 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5288 switch (encoding)
5289 {
5290 case eEncodingT1:
5291 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5292 t = Bits32 (opcode, 2, 0);
5293 n = Bits32 (opcode, 5, 3);
5294 imm32 = Bits32 (opcode, 10, 6);
5295
5296 // index = TRUE; add = TRUE; wback = FALSE;
5297 index = true;
5298 add = true;
5299 wback= false;
5300
5301 break;
5302
5303 case eEncodingT2:
5304 // if Rt == ’1111’ then SEE PLD;
5305 // if Rn == ’1111’ then SEE LDRB (literal);
5306 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5307 t = Bits32 (opcode, 15, 12);
5308 n = Bits32 (opcode, 19, 16);
5309 imm32 = Bits32 (opcode, 11, 0);
5310
5311 // index = TRUE; add = TRUE; wback = FALSE;
5312 index = true;
5313 add = true;
5314 wback = false;
5315
5316 // if t == 13 then UNPREDICTABLE;
5317 if (t == 13)
5318 return false;
5319
5320 break;
5321
5322 case eEncodingT3:
5323 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5324 // if Rn == ’1111’ then SEE LDRB (literal);
5325 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5326 // if P == ’0’ && W == ’0’ then UNDEFINED;
5327 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5328 return false;
5329
5330 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5331 t = Bits32 (opcode, 15, 12);
5332 n = Bits32 (opcode, 19, 16);
5333 imm32 = Bits32 (opcode, 7, 0);
5334
5335 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5336 index = BitIsSet (opcode, 10);
5337 add = BitIsSet (opcode, 9);
5338 wback = BitIsSet (opcode, 8);
5339
5340 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5341 if (BadReg (t) || (wback && (n == t)))
5342 return false;
5343
5344 break;
5345
5346 default:
5347 return false;
5348 }
5349
5350 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5351 if (!success)
5352 return false;
5353
5354 addr_t address;
5355 addr_t offset_addr;
5356
5357 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5358 if (add)
5359 offset_addr = Rn + imm32;
5360 else
5361 offset_addr = Rn - imm32;
5362
5363 // address = if index then offset_addr else R[n];
5364 if (index)
5365 address = offset_addr;
5366 else
5367 address = Rn;
5368
5369 // R[t] = ZeroExtend(MemU[address,1], 32);
5370 Register base_reg;
5371 Register data_reg;
5372 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5373 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5374
5375 EmulateInstruction::Context context;
5376 context.type = eContextRegisterLoad;
5377 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5378
5379 uint64_t data = MemURead (context, address, 1, 0, &success);
5380 if (!success)
5381 return false;
5382
5383 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5384 return false;
5385
5386 // if wback then R[n] = offset_addr;
5387 if (wback)
5388 {
5389 context.type = eContextAdjustBaseRegister;
5390 context.SetAddress (offset_addr);
5391 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5392 return false;
5393 }
5394 }
5395 return true;
5396}
Caroline Ticef55261f2011-02-18 22:24:22 +00005397
5398// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5399// zero-extends it to form a 32-bit word and writes it to a register.
5400bool
5401EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5402{
5403#if 0
5404 if ConditionPassed() then
5405 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5406 base = Align(PC,4);
5407 address = if add then (base + imm32) else (base - imm32);
5408 R[t] = ZeroExtend(MemU[address,1], 32);
5409#endif
5410
5411 bool success = false;
5412 const uint32_t opcode = OpcodeAsUnsigned (&success);
5413 if (!success)
5414 return false;
5415
5416 if (ConditionPassed ())
5417 {
5418 uint32_t t;
5419 uint32_t imm32;
5420 bool add;
5421 switch (encoding)
5422 {
5423 case eEncodingT1:
5424 // if Rt == ’1111’ then SEE PLD;
5425 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5426 t = Bits32 (opcode, 15, 12);
5427 imm32 = Bits32 (opcode, 11, 0);
5428 add = BitIsSet (opcode, 23);
5429
5430 // if t == 13 then UNPREDICTABLE;
5431 if (t == 13)
5432 return false;
5433
5434 break;
5435
5436 case eEncodingA1:
5437 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5438 t = Bits32 (opcode, 15, 12);
5439 imm32 = Bits32 (opcode, 11, 0);
5440 add = BitIsSet (opcode, 23);
5441
5442 // if t == 15 then UNPREDICTABLE;
5443 if (t == 15)
5444 return false;
5445 break;
5446
5447 default:
5448 return false;
5449 }
5450
5451 // base = Align(PC,4);
5452 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5453 if (!success)
5454 return false;
5455
5456 uint32_t base = AlignPC (pc_val);
5457
5458 addr_t address;
5459 // address = if add then (base + imm32) else (base - imm32);
5460 if (add)
5461 address = base + imm32;
5462 else
5463 address = base - imm32;
5464
5465 // R[t] = ZeroExtend(MemU[address,1], 32);
5466 EmulateInstruction::Context context;
5467 context.type = eContextRelativeBranchImmediate;
5468 context.SetImmediate (address - base);
5469
5470 uint64_t data = MemURead (context, address, 1, 0, &success);
5471 if (!success)
5472 return false;
5473
5474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5475 return false;
5476 }
5477 return true;
5478}
Caroline Tice30fec122011-02-18 23:52:21 +00005479
5480// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5481// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5482// optionally be shifted.
5483bool
5484EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5485{
5486#if 0
5487 if ConditionPassed() then
5488 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5489 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5490 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5491 address = if index then offset_addr else R[n];
5492 R[t] = ZeroExtend(MemU[address,1],32);
5493 if wback then R[n] = offset_addr;
5494#endif
5495
5496 bool success = false;
5497 const uint32_t opcode = OpcodeAsUnsigned (&success);
5498 if (!success)
5499 return false;
5500
5501 if (ConditionPassed ())
5502 {
5503 uint32_t t;
5504 uint32_t n;
5505 uint32_t m;
5506 bool index;
5507 bool add;
5508 bool wback;
5509 ARM_ShifterType shift_t;
5510 uint32_t shift_n;
5511
5512 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5513 switch (encoding)
5514 {
5515 case eEncodingT1:
5516 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5517 t = Bits32 (opcode, 2, 0);
5518 n = Bits32 (opcode, 5, 3);
5519 m = Bits32 (opcode, 8, 6);
5520
5521 // index = TRUE; add = TRUE; wback = FALSE;
5522 index = true;
5523 add = true;
5524 wback = false;
5525
5526 // (shift_t, shift_n) = (SRType_LSL, 0);
5527 shift_t = SRType_LSL;
5528 shift_n = 0;
5529 break;
5530
5531 case eEncodingT2:
5532 // if Rt == ’1111’ then SEE PLD;
5533 // if Rn == ’1111’ then SEE LDRB (literal);
5534 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5535 t = Bits32 (opcode, 15, 12);
5536 n = Bits32 (opcode, 19, 16);
5537 m = Bits32 (opcode, 3, 0);
5538
5539 // index = TRUE; add = TRUE; wback = FALSE;
5540 index = true;
5541 add = true;
5542 wback = false;
5543
5544 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5545 shift_t = SRType_LSL;
5546 shift_n = Bits32 (opcode, 5, 4);
5547
5548 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5549 if ((t == 13) || BadReg (m))
5550 return false;
5551 break;
5552
5553 case eEncodingA1:
5554 {
5555 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5556 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5557 t = Bits32 (opcode, 15, 12);
5558 n = Bits32 (opcode, 19, 16);
5559 m = Bits32 (opcode, 3, 0);
5560
5561 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5562 index = BitIsSet (opcode, 24);
5563 add = BitIsSet (opcode, 23);
5564 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5565
5566 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5567 uint32_t type = Bits32 (opcode, 6, 5);
5568 uint32_t imm5 = Bits32 (opcode, 11, 7);
5569 shift_n = DecodeImmShift (type, imm5, shift_t);
5570
5571 // if t == 15 || m == 15 then UNPREDICTABLE;
5572 if ((t == 15) || (m == 15))
5573 return false;
5574
5575 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5576 if (wback && ((n == 15) || (n == t)))
5577 return false;
5578 }
5579 break;
5580
5581 default:
5582 return false;
5583 }
5584
5585 addr_t offset_addr;
5586 addr_t address;
5587
5588 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5589 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5590 if (!success)
5591 return false;
5592
5593 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5594
5595 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5596 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5597 if (!success)
5598 return false;
5599
5600 if (add)
5601 offset_addr = Rn + offset;
5602 else
5603 offset_addr = Rn - offset;
5604
5605 // address = if index then offset_addr else R[n];
5606 if (index)
5607 address = offset_addr;
5608 else
5609 address = Rn;
5610
5611 // R[t] = ZeroExtend(MemU[address,1],32);
5612 Register base_reg;
5613 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5614
5615 EmulateInstruction::Context context;
5616 context.type = eContextRegisterLoad;
5617 context.SetRegisterPlusOffset (base_reg, address - Rn);
5618
5619 uint64_t data = MemURead (context, address, 1, 0, &success);
5620 if (!success)
5621 return false;
5622
5623 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5624 return false;
5625
5626 // if wback then R[n] = offset_addr;
5627 if (wback)
5628 {
5629 context.type = eContextAdjustBaseRegister;
5630 context.SetAddress (offset_addr);
5631 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5632 return false;
5633 }
5634 }
5635 return true;
5636}
Caroline Ticefe479112011-02-18 18:52:37 +00005637
Johnny Chen2115b412011-02-21 23:42:44 +00005638// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5639// and writes the result to the destination register. It can optionally update the condition flags based on
5640// the result.
5641bool
5642EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5643{
5644#if 0
5645 // ARM pseudo code...
5646 if ConditionPassed() then
5647 EncodingSpecificOperations();
5648 result = R[n] EOR imm32;
5649 if d == 15 then // Can only occur for ARM encoding
5650 ALUWritePC(result); // setflags is always FALSE here
5651 else
5652 R[d] = result;
5653 if setflags then
5654 APSR.N = result<31>;
5655 APSR.Z = IsZeroBit(result);
5656 APSR.C = carry;
5657 // APSR.V unchanged
5658#endif
5659
5660 bool success = false;
5661 const uint32_t opcode = OpcodeAsUnsigned (&success);
5662 if (!success)
5663 return false;
5664
5665 if (ConditionPassed())
5666 {
5667 uint32_t Rd, Rn;
5668 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5669 bool setflags;
5670 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5671 switch (encoding)
5672 {
5673 case eEncodingT1:
5674 Rd = Bits32(opcode, 11, 8);
5675 Rn = Bits32(opcode, 19, 16);
5676 setflags = BitIsSet(opcode, 20);
5677 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5678 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5679 if (Rd == 15 && setflags)
5680 return EmulateTEQImm(eEncodingT1);
5681 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5682 return false;
5683 break;
5684 case eEncodingA1:
5685 Rd = Bits32(opcode, 15, 12);
5686 Rn = Bits32(opcode, 19, 16);
5687 setflags = BitIsSet(opcode, 20);
5688 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5689 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5690 // TODO: Emulate SUBS PC, LR and related instructions.
5691 if (Rd == 15 && setflags)
5692 return false;
5693 break;
5694 default:
5695 return false;
5696 }
5697
5698 // Read the first operand.
5699 uint32_t val1 = ReadCoreReg(Rn, &success);
5700 if (!success)
5701 return false;
5702
5703 uint32_t result = val1 ^ imm32;
5704
5705 EmulateInstruction::Context context;
5706 context.type = EmulateInstruction::eContextImmediate;
5707 context.SetNoArgs ();
5708
5709 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5710 return false;
5711 }
5712 return true;
5713}
5714
5715// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5716// optionally-shifted register value, and writes the result to the destination register.
5717// It can optionally update the condition flags based on the result.
5718bool
5719EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5720{
5721#if 0
5722 // ARM pseudo code...
5723 if ConditionPassed() then
5724 EncodingSpecificOperations();
5725 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5726 result = R[n] EOR shifted;
5727 if d == 15 then // Can only occur for ARM encoding
5728 ALUWritePC(result); // setflags is always FALSE here
5729 else
5730 R[d] = result;
5731 if setflags then
5732 APSR.N = result<31>;
5733 APSR.Z = IsZeroBit(result);
5734 APSR.C = carry;
5735 // APSR.V unchanged
5736#endif
5737
5738 bool success = false;
5739 const uint32_t opcode = OpcodeAsUnsigned (&success);
5740 if (!success)
5741 return false;
5742
5743 if (ConditionPassed())
5744 {
5745 uint32_t Rd, Rn, Rm;
5746 ARM_ShifterType shift_t;
5747 uint32_t shift_n; // the shift applied to the value read from Rm
5748 bool setflags;
5749 uint32_t carry;
5750 switch (encoding)
5751 {
5752 case eEncodingT1:
5753 Rd = Rn = Bits32(opcode, 2, 0);
5754 Rm = Bits32(opcode, 5, 3);
5755 setflags = !InITBlock();
5756 shift_t = SRType_LSL;
5757 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005758 break;
Johnny Chen2115b412011-02-21 23:42:44 +00005759 case eEncodingT2:
5760 Rd = Bits32(opcode, 11, 8);
5761 Rn = Bits32(opcode, 19, 16);
5762 Rm = Bits32(opcode, 3, 0);
5763 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005764 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5765 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005766 if (Rd == 15 && setflags)
5767 return EmulateTEQReg(eEncodingT1);
5768 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5769 return false;
5770 break;
5771 case eEncodingA1:
5772 Rd = Bits32(opcode, 15, 12);
5773 Rn = Bits32(opcode, 19, 16);
5774 Rm = Bits32(opcode, 3, 0);
5775 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005776 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005777 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5778 // TODO: Emulate SUBS PC, LR and related instructions.
5779 if (Rd == 15 && setflags)
5780 return false;
5781 break;
5782 default:
5783 return false;
5784 }
5785
5786 // Read the first operand.
5787 uint32_t val1 = ReadCoreReg(Rn, &success);
5788 if (!success)
5789 return false;
5790
5791 // Read the second operand.
5792 uint32_t val2 = ReadCoreReg(Rm, &success);
5793 if (!success)
5794 return false;
5795
5796 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5797 uint32_t result = val1 ^ shifted;
5798
5799 EmulateInstruction::Context context;
5800 context.type = EmulateInstruction::eContextImmediate;
5801 context.SetNoArgs ();
5802
5803 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5804 return false;
5805 }
5806 return true;
5807}
5808
Johnny Chen7c5234d2011-02-18 23:41:11 +00005809// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5810// writes the result to the destination register. It can optionally update the condition flags based
5811// on the result.
5812bool
5813EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5814{
5815#if 0
5816 // ARM pseudo code...
5817 if ConditionPassed() then
5818 EncodingSpecificOperations();
5819 result = R[n] OR imm32;
5820 if d == 15 then // Can only occur for ARM encoding
5821 ALUWritePC(result); // setflags is always FALSE here
5822 else
5823 R[d] = result;
5824 if setflags then
5825 APSR.N = result<31>;
5826 APSR.Z = IsZeroBit(result);
5827 APSR.C = carry;
5828 // APSR.V unchanged
5829#endif
5830
5831 bool success = false;
5832 const uint32_t opcode = OpcodeAsUnsigned (&success);
5833 if (!success)
5834 return false;
5835
5836 if (ConditionPassed())
5837 {
5838 uint32_t Rd, Rn;
5839 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5840 bool setflags;
5841 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5842 switch (encoding)
5843 {
5844 case eEncodingT1:
5845 Rd = Bits32(opcode, 11, 8);
5846 Rn = Bits32(opcode, 19, 16);
5847 setflags = BitIsSet(opcode, 20);
5848 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5849 // if Rn == ‘1111’ then SEE MOV (immediate);
5850 if (Rn == 15)
5851 return EmulateMOVRdImm(eEncodingT2);
5852 if (BadReg(Rd) || Rn == 13)
5853 return false;
5854 break;
5855 case eEncodingA1:
5856 Rd = Bits32(opcode, 15, 12);
5857 Rn = Bits32(opcode, 19, 16);
5858 setflags = BitIsSet(opcode, 20);
5859 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5860 // TODO: Emulate SUBS PC, LR and related instructions.
5861 if (Rd == 15 && setflags)
5862 return false;
5863 break;
5864 default:
5865 return false;
5866 }
5867
5868 // Read the first operand.
5869 uint32_t val1 = ReadCoreReg(Rn, &success);
5870 if (!success)
5871 return false;
5872
5873 uint32_t result = val1 | imm32;
5874
5875 EmulateInstruction::Context context;
5876 context.type = EmulateInstruction::eContextImmediate;
5877 context.SetNoArgs ();
5878
5879 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5880 return false;
5881 }
5882 return true;
5883}
5884
5885// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5886// value, and writes the result to the destination register. It can optionally update the condition flags based
5887// on the result.
5888bool
5889EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5890{
5891#if 0
5892 // ARM pseudo code...
5893 if ConditionPassed() then
5894 EncodingSpecificOperations();
5895 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5896 result = R[n] OR shifted;
5897 if d == 15 then // Can only occur for ARM encoding
5898 ALUWritePC(result); // setflags is always FALSE here
5899 else
5900 R[d] = result;
5901 if setflags then
5902 APSR.N = result<31>;
5903 APSR.Z = IsZeroBit(result);
5904 APSR.C = carry;
5905 // APSR.V unchanged
5906#endif
5907
5908 bool success = false;
5909 const uint32_t opcode = OpcodeAsUnsigned (&success);
5910 if (!success)
5911 return false;
5912
5913 if (ConditionPassed())
5914 {
5915 uint32_t Rd, Rn, Rm;
5916 ARM_ShifterType shift_t;
5917 uint32_t shift_n; // the shift applied to the value read from Rm
5918 bool setflags;
5919 uint32_t carry;
5920 switch (encoding)
5921 {
5922 case eEncodingT1:
5923 Rd = Rn = Bits32(opcode, 2, 0);
5924 Rm = Bits32(opcode, 5, 3);
5925 setflags = !InITBlock();
5926 shift_t = SRType_LSL;
5927 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005928 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005929 case eEncodingT2:
5930 Rd = Bits32(opcode, 11, 8);
5931 Rn = Bits32(opcode, 19, 16);
5932 Rm = Bits32(opcode, 3, 0);
5933 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005934 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5935 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005936 if (Rn == 15)
5937 return EmulateMOVRdRm(eEncodingT3);
5938 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5939 return false;
5940 break;
5941 case eEncodingA1:
5942 Rd = Bits32(opcode, 15, 12);
5943 Rn = Bits32(opcode, 19, 16);
5944 Rm = Bits32(opcode, 3, 0);
5945 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005946 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005947 // TODO: Emulate SUBS PC, LR and related instructions.
5948 if (Rd == 15 && setflags)
5949 return false;
5950 break;
5951 default:
5952 return false;
5953 }
5954
5955 // Read the first operand.
5956 uint32_t val1 = ReadCoreReg(Rn, &success);
5957 if (!success)
5958 return false;
5959
5960 // Read the second operand.
5961 uint32_t val2 = ReadCoreReg(Rm, &success);
5962 if (!success)
5963 return false;
5964
5965 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005966 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005967
5968 EmulateInstruction::Context context;
5969 context.type = EmulateInstruction::eContextImmediate;
5970 context.SetNoArgs ();
5971
5972 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5973 return false;
5974 }
5975 return true;
5976}
5977
Johnny Chened32e7c2011-02-22 23:42:58 +00005978// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
5979// the destination register. It can optionally update the condition flags based on the result.
5980bool
5981EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
5982{
5983#if 0
5984 // ARM pseudo code...
5985 if ConditionPassed() then
5986 EncodingSpecificOperations();
5987 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
5988 if d == 15 then // Can only occur for ARM encoding
5989 ALUWritePC(result); // setflags is always FALSE here
5990 else
5991 R[d] = result;
5992 if setflags then
5993 APSR.N = result<31>;
5994 APSR.Z = IsZeroBit(result);
5995 APSR.C = carry;
5996 APSR.V = overflow;
5997#endif
5998
5999 bool success = false;
6000 const uint32_t opcode = OpcodeAsUnsigned (&success);
6001 if (!success)
6002 return false;
6003
6004 uint32_t Rd; // the destination register
6005 uint32_t Rn; // the first operand
6006 bool setflags;
6007 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6008 switch (encoding) {
6009 case eEncodingT1:
6010 Rd = Bits32(opcode, 2, 0);
6011 Rn = Bits32(opcode, 5, 3);
6012 setflags = !InITBlock();
6013 imm32 = 0;
6014 break;
6015 case eEncodingT2:
6016 Rd = Bits32(opcode, 11, 8);
6017 Rn = Bits32(opcode, 19, 16);
6018 setflags = BitIsSet(opcode, 20);
6019 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6020 if (BadReg(Rd) || BadReg(Rn))
6021 return false;
6022 break;
6023 case eEncodingA1:
6024 Rd = Bits32(opcode, 15, 12);
6025 Rn = Bits32(opcode, 19, 16);
6026 setflags = BitIsSet(opcode, 20);
6027 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6028 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6029 // TODO: Emulate SUBS PC, LR and related instructions.
6030 if (Rd == 15 && setflags)
6031 return false;
6032 break;
6033 default:
6034 return false;
6035 }
6036 // Read the register value from the operand register Rn.
6037 uint32_t reg_val = ReadCoreReg(Rn, &success);
6038 if (!success)
6039 return false;
6040
6041 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
6042
6043 EmulateInstruction::Context context;
6044 context.type = EmulateInstruction::eContextImmediate;
6045 context.SetNoArgs ();
6046
6047 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6048 return false;
6049
6050 return true;
6051}
6052
6053// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
6054// result to the destination register. It can optionally update the condition flags based on the result.
6055bool
6056EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
6057{
6058#if 0
6059 // ARM pseudo code...
6060 if ConditionPassed() then
6061 EncodingSpecificOperations();
6062 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6063 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
6064 if d == 15 then // Can only occur for ARM encoding
6065 ALUWritePC(result); // setflags is always FALSE here
6066 else
6067 R[d] = result;
6068 if setflags then
6069 APSR.N = result<31>;
6070 APSR.Z = IsZeroBit(result);
6071 APSR.C = carry;
6072 APSR.V = overflow;
6073#endif
6074
6075 bool success = false;
6076 const uint32_t opcode = OpcodeAsUnsigned (&success);
6077 if (!success)
6078 return false;
6079
6080 uint32_t Rd; // the destination register
6081 uint32_t Rn; // the first operand
6082 uint32_t Rm; // the second operand
6083 bool setflags;
6084 ARM_ShifterType shift_t;
6085 uint32_t shift_n; // the shift applied to the value read from Rm
6086 switch (encoding) {
6087 case eEncodingT1:
6088 Rd = Bits32(opcode, 11, 8);
6089 Rn = Bits32(opcode, 19, 16);
6090 Rm = Bits32(opcode, 3, 0);
6091 setflags = BitIsSet(opcode, 20);
6092 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6093 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6094 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6095 return false;
6096 break;
6097 case eEncodingA1:
6098 Rd = Bits32(opcode, 15, 12);
6099 Rn = Bits32(opcode, 19, 16);
6100 Rm = Bits32(opcode, 3, 0);
6101 setflags = BitIsSet(opcode, 20);
6102 shift_n = DecodeImmShiftARM(opcode, shift_t);
6103 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6104 // TODO: Emulate SUBS PC, LR and related instructions.
6105 if (Rd == 15 && setflags)
6106 return false;
6107 break;
6108 default:
6109 return false;
6110 }
6111 // Read the register value from register Rn.
6112 uint32_t val1 = ReadCoreReg(Rn, &success);
6113 if (!success)
6114 return false;
6115
6116 // Read the register value from register Rm.
6117 uint32_t val2 = ReadCoreReg(Rm, &success);
6118 if (!success)
6119 return false;
6120
6121 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6122 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6123
6124 EmulateInstruction::Context context;
6125 context.type = EmulateInstruction::eContextImmediate;
6126 context.SetNoArgs();
6127 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6128 return false;
6129
6130 return true;
6131}
6132
Johnny Chen90e607b2011-02-23 00:07:09 +00006133// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
6134// an immediate value, and writes the result to the destination register. It can optionally update the condition
6135// flags based on the result.
6136bool
6137EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
6138{
6139#if 0
6140 // ARM pseudo code...
6141 if ConditionPassed() then
6142 EncodingSpecificOperations();
6143 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
6144 if d == 15 then
6145 ALUWritePC(result); // setflags is always FALSE here
6146 else
6147 R[d] = result;
6148 if setflags then
6149 APSR.N = result<31>;
6150 APSR.Z = IsZeroBit(result);
6151 APSR.C = carry;
6152 APSR.V = overflow;
6153#endif
6154
6155 bool success = false;
6156 const uint32_t opcode = OpcodeAsUnsigned (&success);
6157 if (!success)
6158 return false;
6159
6160 uint32_t Rd; // the destination register
6161 uint32_t Rn; // the first operand
6162 bool setflags;
6163 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6164 switch (encoding) {
6165 case eEncodingA1:
6166 Rd = Bits32(opcode, 15, 12);
6167 Rn = Bits32(opcode, 19, 16);
6168 setflags = BitIsSet(opcode, 20);
6169 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6170 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6171 // TODO: Emulate SUBS PC, LR and related instructions.
6172 if (Rd == 15 && setflags)
6173 return false;
6174 break;
6175 default:
6176 return false;
6177 }
6178 // Read the register value from the operand register Rn.
6179 uint32_t reg_val = ReadCoreReg(Rn, &success);
6180 if (!success)
6181 return false;
6182
6183 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
6184
6185 EmulateInstruction::Context context;
6186 context.type = EmulateInstruction::eContextImmediate;
6187 context.SetNoArgs ();
6188
6189 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6190 return false;
6191
6192 return true;
6193}
6194
6195// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
6196// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
6197// condition flags based on the result.
6198bool
6199EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
6200{
6201#if 0
6202 // ARM pseudo code...
6203 if ConditionPassed() then
6204 EncodingSpecificOperations();
6205 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6206 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
6207 if d == 15 then
6208 ALUWritePC(result); // setflags is always FALSE here
6209 else
6210 R[d] = result;
6211 if setflags then
6212 APSR.N = result<31>;
6213 APSR.Z = IsZeroBit(result);
6214 APSR.C = carry;
6215 APSR.V = overflow;
6216#endif
6217
6218 bool success = false;
6219 const uint32_t opcode = OpcodeAsUnsigned (&success);
6220 if (!success)
6221 return false;
6222
6223 uint32_t Rd; // the destination register
6224 uint32_t Rn; // the first operand
6225 uint32_t Rm; // the second operand
6226 bool setflags;
6227 ARM_ShifterType shift_t;
6228 uint32_t shift_n; // the shift applied to the value read from Rm
6229 switch (encoding) {
6230 case eEncodingA1:
6231 Rd = Bits32(opcode, 15, 12);
6232 Rn = Bits32(opcode, 19, 16);
6233 Rm = Bits32(opcode, 3, 0);
6234 setflags = BitIsSet(opcode, 20);
6235 shift_n = DecodeImmShiftARM(opcode, shift_t);
6236 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6237 // TODO: Emulate SUBS PC, LR and related instructions.
6238 if (Rd == 15 && setflags)
6239 return false;
6240 break;
6241 default:
6242 return false;
6243 }
6244 // Read the register value from register Rn.
6245 uint32_t val1 = ReadCoreReg(Rn, &success);
6246 if (!success)
6247 return false;
6248
6249 // Read the register value from register Rm.
6250 uint32_t val2 = ReadCoreReg(Rm, &success);
6251 if (!success)
6252 return false;
6253
6254 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6255 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
6256
6257 EmulateInstruction::Context context;
6258 context.type = EmulateInstruction::eContextImmediate;
6259 context.SetNoArgs();
6260 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6261 return false;
6262
6263 return true;
6264}
6265
Johnny Chen9b381772011-02-23 01:01:21 +00006266// Subtract with Carry (immediate) subtracts an immediate value and the value of
6267// NOT (Carry flag) from a register value, and writes the result to the destination register.
6268// It can optionally update the condition flags based on the result.
6269bool
6270EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
6271{
6272#if 0
6273 // ARM pseudo code...
6274 if ConditionPassed() then
6275 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006276 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00006277 if d == 15 then // Can only occur for ARM encoding
6278 ALUWritePC(result); // setflags is always FALSE here
6279 else
6280 R[d] = result;
6281 if setflags then
6282 APSR.N = result<31>;
6283 APSR.Z = IsZeroBit(result);
6284 APSR.C = carry;
6285 APSR.V = overflow;
6286#endif
6287
6288 bool success = false;
6289 const uint32_t opcode = OpcodeAsUnsigned (&success);
6290 if (!success)
6291 return false;
6292
6293 uint32_t Rd; // the destination register
6294 uint32_t Rn; // the first operand
6295 bool setflags;
6296 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6297 switch (encoding) {
6298 case eEncodingT1:
6299 Rd = Bits32(opcode, 11, 8);
6300 Rn = Bits32(opcode, 19, 16);
6301 setflags = BitIsSet(opcode, 20);
6302 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6303 if (BadReg(Rd) || BadReg(Rn))
6304 return false;
6305 break;
6306 case eEncodingA1:
6307 Rd = Bits32(opcode, 15, 12);
6308 Rn = Bits32(opcode, 19, 16);
6309 setflags = BitIsSet(opcode, 20);
6310 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6311 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6312 // TODO: Emulate SUBS PC, LR and related instructions.
6313 if (Rd == 15 && setflags)
6314 return false;
6315 break;
6316 default:
6317 return false;
6318 }
6319 // Read the register value from the operand register Rn.
6320 uint32_t reg_val = ReadCoreReg(Rn, &success);
6321 if (!success)
6322 return false;
6323
6324 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
6325
6326 EmulateInstruction::Context context;
6327 context.type = EmulateInstruction::eContextImmediate;
6328 context.SetNoArgs ();
6329
6330 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6331 return false;
6332
6333 return true;
6334}
6335
6336// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
6337// NOT (Carry flag) from a register value, and writes the result to the destination register.
6338// It can optionally update the condition flags based on the result.
6339bool
6340EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
6341{
6342#if 0
6343 // ARM pseudo code...
6344 if ConditionPassed() then
6345 EncodingSpecificOperations();
6346 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6347 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
6348 if d == 15 then // Can only occur for ARM encoding
6349 ALUWritePC(result); // setflags is always FALSE here
6350 else
6351 R[d] = result;
6352 if setflags then
6353 APSR.N = result<31>;
6354 APSR.Z = IsZeroBit(result);
6355 APSR.C = carry;
6356 APSR.V = overflow;
6357#endif
6358
6359 bool success = false;
6360 const uint32_t opcode = OpcodeAsUnsigned (&success);
6361 if (!success)
6362 return false;
6363
6364 uint32_t Rd; // the destination register
6365 uint32_t Rn; // the first operand
6366 uint32_t Rm; // the second operand
6367 bool setflags;
6368 ARM_ShifterType shift_t;
6369 uint32_t shift_n; // the shift applied to the value read from Rm
6370 switch (encoding) {
6371 case eEncodingT1:
6372 Rd = Rn = Bits32(opcode, 2, 0);
6373 Rm = Bits32(opcode, 5, 3);
6374 setflags = !InITBlock();
6375 shift_t = SRType_LSL;
6376 shift_n = 0;
6377 break;
6378 case eEncodingT2:
6379 Rd = Bits32(opcode, 11, 8);
6380 Rn = Bits32(opcode, 19, 16);
6381 Rm = Bits32(opcode, 3, 0);
6382 setflags = BitIsSet(opcode, 20);
6383 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6384 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6385 return false;
6386 break;
6387 case eEncodingA1:
6388 Rd = Bits32(opcode, 15, 12);
6389 Rn = Bits32(opcode, 19, 16);
6390 Rm = Bits32(opcode, 3, 0);
6391 setflags = BitIsSet(opcode, 20);
6392 shift_n = DecodeImmShiftARM(opcode, shift_t);
6393 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6394 // TODO: Emulate SUBS PC, LR and related instructions.
6395 if (Rd == 15 && setflags)
6396 return false;
6397 break;
6398 default:
6399 return false;
6400 }
6401 // Read the register value from register Rn.
6402 uint32_t val1 = ReadCoreReg(Rn, &success);
6403 if (!success)
6404 return false;
6405
6406 // Read the register value from register Rm.
6407 uint32_t val2 = ReadCoreReg(Rm, &success);
6408 if (!success)
6409 return false;
6410
6411 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6412 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
6413
6414 EmulateInstruction::Context context;
6415 context.type = EmulateInstruction::eContextImmediate;
6416 context.SetNoArgs();
6417 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6418 return false;
6419
6420 return true;
6421}
6422
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006423// This instruction subtracts an immediate value from a register value, and writes the result
6424// to the destination register. It can optionally update the condition flags based on the result.
6425bool
6426EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
6427{
6428#if 0
6429 // ARM pseudo code...
6430 if ConditionPassed() then
6431 EncodingSpecificOperations();
6432 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
6433 R[d] = result;
6434 if setflags then
6435 APSR.N = result<31>;
6436 APSR.Z = IsZeroBit(result);
6437 APSR.C = carry;
6438 APSR.V = overflow;
6439#endif
6440
6441 bool success = false;
6442 const uint32_t opcode = OpcodeAsUnsigned (&success);
6443 if (!success)
6444 return false;
6445
6446 uint32_t Rd; // the destination register
6447 uint32_t Rn; // the first operand
6448 bool setflags;
6449 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
6450 switch (encoding) {
6451 case eEncodingT1:
6452 Rd = Bits32(opcode, 2, 0);
6453 Rn = Bits32(opcode, 5, 3);
6454 setflags = !InITBlock();
6455 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
6456 break;
6457 case eEncodingT2:
6458 Rd = Rn = Bits32(opcode, 10, 8);
6459 setflags = !InITBlock();
6460 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
6461 break;
6462 case eEncodingT3:
6463 Rd = Bits32(opcode, 11, 8);
6464 Rn = Bits32(opcode, 19, 16);
6465 setflags = BitIsSet(opcode, 20);
6466 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6467
6468 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
6469 if (Rd == 15 && setflags)
6470 return EmulateCMPImm(eEncodingT2);
6471
6472 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
6473 if (Rn == 13)
6474 return EmulateSUBSPImm(eEncodingT2);
6475
6476 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
6477 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
6478 return false;
6479 break;
6480 case eEncodingT4:
6481 Rd = Bits32(opcode, 11, 8);
6482 Rn = Bits32(opcode, 19, 16);
6483 setflags = BitIsSet(opcode, 20);
6484 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
6485
6486 // if Rn == '1111' then SEE ADR;
6487 if (Rn == 15)
6488 return EmulateADR(eEncodingT2);
6489
6490 // if Rn == '1101' then SEE SUB (SP minus immediate);
6491 if (Rn == 13)
6492 return EmulateSUBSPImm(eEncodingT3);
6493
6494 if (BadReg(Rd))
6495 return false;
6496 break;
6497 default:
6498 return false;
6499 }
6500 // Read the register value from the operand register Rn.
6501 uint32_t reg_val = ReadCoreReg(Rn, &success);
6502 if (!success)
6503 return false;
6504
6505 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
6506
6507 EmulateInstruction::Context context;
6508 context.type = EmulateInstruction::eContextImmediate;
6509 context.SetNoArgs ();
6510
6511 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6512 return false;
6513
6514 return true;
6515}
6516
6517// This instruction subtracts an immediate value from a register value, and writes the result
6518// to the destination register. It can optionally update the condition flags based on the result.
6519bool
6520EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
6521{
6522#if 0
6523 // ARM pseudo code...
6524 if ConditionPassed() then
6525 EncodingSpecificOperations();
6526 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
6527 if d == 15 then
6528 ALUWritePC(result); // setflags is always FALSE here
6529 else
6530 R[d] = result;
6531 if setflags then
6532 APSR.N = result<31>;
6533 APSR.Z = IsZeroBit(result);
6534 APSR.C = carry;
6535 APSR.V = overflow;
6536#endif
6537
6538 bool success = false;
6539 const uint32_t opcode = OpcodeAsUnsigned (&success);
6540 if (!success)
6541 return false;
6542
6543 uint32_t Rd; // the destination register
6544 uint32_t Rn; // the first operand
6545 bool setflags;
6546 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
6547 switch (encoding) {
6548 case eEncodingA1:
6549 Rd = Bits32(opcode, 15, 12);
6550 Rn = Bits32(opcode, 19, 16);
6551 setflags = BitIsSet(opcode, 20);
6552 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6553
6554 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
6555 if (Rn == 15 && !setflags)
6556 return EmulateADR(eEncodingA2);
6557
6558 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
6559 if (Rn == 13)
6560 return EmulateSUBSPImm(eEncodingA1);
6561
6562 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6563 // TODO: Emulate SUBS PC, LR and related instructions.
6564 if (Rd == 15 && setflags)
6565 return false;
6566 break;
6567 default:
6568 return false;
6569 }
6570 // Read the register value from the operand register Rn.
6571 uint32_t reg_val = ReadCoreReg(Rn, &success);
6572 if (!success)
6573 return false;
6574
6575 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
6576
6577 EmulateInstruction::Context context;
6578 context.type = EmulateInstruction::eContextImmediate;
6579 context.SetNoArgs ();
6580
6581 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6582 return false;
6583
6584 return true;
6585}
6586
Johnny Chen2115b412011-02-21 23:42:44 +00006587// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
6588// immediate value. It updates the condition flags based on the result, and discards the result.
6589bool
6590EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
6591{
6592#if 0
6593 // ARM pseudo code...
6594 if ConditionPassed() then
6595 EncodingSpecificOperations();
6596 result = R[n] EOR imm32;
6597 APSR.N = result<31>;
6598 APSR.Z = IsZeroBit(result);
6599 APSR.C = carry;
6600 // APSR.V unchanged
6601#endif
6602
6603 bool success = false;
6604 const uint32_t opcode = OpcodeAsUnsigned (&success);
6605 if (!success)
6606 return false;
6607
6608 if (ConditionPassed())
6609 {
6610 uint32_t Rn;
6611 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6612 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6613 switch (encoding)
6614 {
6615 case eEncodingT1:
6616 Rn = Bits32(opcode, 19, 16);
6617 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6618 if (BadReg(Rn))
6619 return false;
6620 break;
6621 case eEncodingA1:
6622 Rn = Bits32(opcode, 19, 16);
6623 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6624 break;
6625 default:
6626 return false;
6627 }
6628
6629 // Read the first operand.
6630 uint32_t val1 = ReadCoreReg(Rn, &success);
6631 if (!success)
6632 return false;
6633
6634 uint32_t result = val1 ^ imm32;
6635
6636 EmulateInstruction::Context context;
6637 context.type = EmulateInstruction::eContextImmediate;
6638 context.SetNoArgs ();
6639
6640 if (!WriteFlags(context, result, carry))
6641 return false;
6642 }
6643 return true;
6644}
6645
6646// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
6647// optionally-shifted register value. It updates the condition flags based on the result, and discards
6648// the result.
6649bool
6650EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
6651{
6652#if 0
6653 // ARM pseudo code...
6654 if ConditionPassed() then
6655 EncodingSpecificOperations();
6656 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6657 result = R[n] EOR shifted;
6658 APSR.N = result<31>;
6659 APSR.Z = IsZeroBit(result);
6660 APSR.C = carry;
6661 // APSR.V unchanged
6662#endif
6663
6664 bool success = false;
6665 const uint32_t opcode = OpcodeAsUnsigned (&success);
6666 if (!success)
6667 return false;
6668
6669 if (ConditionPassed())
6670 {
6671 uint32_t Rn, Rm;
6672 ARM_ShifterType shift_t;
6673 uint32_t shift_n; // the shift applied to the value read from Rm
6674 uint32_t carry;
6675 switch (encoding)
6676 {
6677 case eEncodingT1:
6678 Rn = Bits32(opcode, 19, 16);
6679 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006680 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006681 if (BadReg(Rn) || BadReg(Rm))
6682 return false;
6683 break;
6684 case eEncodingA1:
6685 Rn = Bits32(opcode, 19, 16);
6686 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006687 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006688 break;
6689 default:
6690 return false;
6691 }
6692
6693 // Read the first operand.
6694 uint32_t val1 = ReadCoreReg(Rn, &success);
6695 if (!success)
6696 return false;
6697
6698 // Read the second operand.
6699 uint32_t val2 = ReadCoreReg(Rm, &success);
6700 if (!success)
6701 return false;
6702
6703 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6704 uint32_t result = val1 ^ shifted;
6705
6706 EmulateInstruction::Context context;
6707 context.type = EmulateInstruction::eContextImmediate;
6708 context.SetNoArgs ();
6709
6710 if (!WriteFlags(context, result, carry))
6711 return false;
6712 }
6713 return true;
6714}
6715
Johnny Chende3cce32011-02-21 21:24:49 +00006716// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
6717// It updates the condition flags based on the result, and discards the result.
6718bool
6719EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6720{
6721#if 0
6722 // ARM pseudo code...
6723 if ConditionPassed() then
6724 EncodingSpecificOperations();
6725 result = R[n] AND imm32;
6726 APSR.N = result<31>;
6727 APSR.Z = IsZeroBit(result);
6728 APSR.C = carry;
6729 // APSR.V unchanged
6730#endif
6731
6732 bool success = false;
6733 const uint32_t opcode = OpcodeAsUnsigned (&success);
6734 if (!success)
6735 return false;
6736
6737 if (ConditionPassed())
6738 {
6739 uint32_t Rn;
6740 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6741 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6742 switch (encoding)
6743 {
6744 case eEncodingT1:
6745 Rn = Bits32(opcode, 19, 16);
6746 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6747 if (BadReg(Rn))
6748 return false;
6749 break;
6750 case eEncodingA1:
6751 Rn = Bits32(opcode, 19, 16);
6752 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6753 break;
6754 default:
6755 return false;
6756 }
6757
6758 // Read the first operand.
6759 uint32_t val1 = ReadCoreReg(Rn, &success);
6760 if (!success)
6761 return false;
6762
6763 uint32_t result = val1 & imm32;
6764
6765 EmulateInstruction::Context context;
6766 context.type = EmulateInstruction::eContextImmediate;
6767 context.SetNoArgs ();
6768
6769 if (!WriteFlags(context, result, carry))
6770 return false;
6771 }
6772 return true;
6773}
6774
6775// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6776// It updates the condition flags based on the result, and discards the result.
6777bool
6778EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6779{
6780#if 0
6781 // ARM pseudo code...
6782 if ConditionPassed() then
6783 EncodingSpecificOperations();
6784 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6785 result = R[n] AND shifted;
6786 APSR.N = result<31>;
6787 APSR.Z = IsZeroBit(result);
6788 APSR.C = carry;
6789 // APSR.V unchanged
6790#endif
6791
6792 bool success = false;
6793 const uint32_t opcode = OpcodeAsUnsigned (&success);
6794 if (!success)
6795 return false;
6796
6797 if (ConditionPassed())
6798 {
6799 uint32_t Rn, Rm;
6800 ARM_ShifterType shift_t;
6801 uint32_t shift_n; // the shift applied to the value read from Rm
6802 uint32_t carry;
6803 switch (encoding)
6804 {
6805 case eEncodingT1:
6806 Rn = Bits32(opcode, 2, 0);
6807 Rm = Bits32(opcode, 5, 3);
6808 shift_t = SRType_LSL;
6809 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006810 break;
Johnny Chende3cce32011-02-21 21:24:49 +00006811 case eEncodingT2:
6812 Rn = Bits32(opcode, 19, 16);
6813 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006814 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006815 if (BadReg(Rn) || BadReg(Rm))
6816 return false;
6817 break;
6818 case eEncodingA1:
6819 Rn = Bits32(opcode, 19, 16);
6820 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006821 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006822 break;
6823 default:
6824 return false;
6825 }
6826
6827 // Read the first operand.
6828 uint32_t val1 = ReadCoreReg(Rn, &success);
6829 if (!success)
6830 return false;
6831
6832 // Read the second operand.
6833 uint32_t val2 = ReadCoreReg(Rm, &success);
6834 if (!success)
6835 return false;
6836
6837 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6838 uint32_t result = val1 & shifted;
6839
6840 EmulateInstruction::Context context;
6841 context.type = EmulateInstruction::eContextImmediate;
6842 context.SetNoArgs ();
6843
6844 if (!WriteFlags(context, result, carry))
6845 return false;
6846 }
6847 return true;
6848}
6849
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006850EmulateInstructionARM::ARMOpcode*
6851EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006852{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006853 static ARMOpcode
6854 g_arm_opcodes[] =
6855 {
6856 //----------------------------------------------------------------------
6857 // Prologue instructions
6858 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006859
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006860 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006861 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6862 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006863
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006864 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006865 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006866 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006867 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006868 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6869 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006870 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006871
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006872 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006873 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006874
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006875 // push one register
6876 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006877 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006878
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006879 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006880 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6881 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006882
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006883 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006884 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006885 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006886
Johnny Chen9f687722011-02-18 00:02:28 +00006887 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6888 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006889 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006890 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6891
6892 //----------------------------------------------------------------------
6893 // Supervisor Call (previously Software Interrupt)
6894 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006895 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6896
6897 //----------------------------------------------------------------------
6898 // Branch instructions
6899 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006900 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006901 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6902 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6903 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6904 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006905 // for example, "bx lr"
6906 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006907
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006908 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006909 // Data-processing instructions
6910 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006911 // adc (immediate)
6912 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6913 // adc (register)
6914 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006915 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006916 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006917 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006918 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00006919 // adr
6920 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
6921 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006922 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006923 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006924 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006925 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006926 // eor (immediate)
6927 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6928 // eor (register)
6929 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006930 // orr (immediate)
6931 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6932 // orr (register)
6933 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006934 // rsb (immediate)
6935 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
6936 // rsb (register)
6937 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00006938 // rsc (immediate)
6939 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
6940 // rsc (register)
6941 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00006942 // sbc (immediate)
6943 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
6944 // sbc (register)
6945 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006946 // sub (immediate, ARM)
6947 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006948 // sub (sp minus immediate)
6949 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00006950 // teq (immediate)
6951 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6952 // teq (register)
6953 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006954 // tst (immediate)
6955 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6956 // tst (register)
6957 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6958
6959
Johnny Chend642a6a2011-02-22 01:01:03 +00006960 // mvn (immediate)
6961 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6962 // mvn (register)
6963 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006964 // cmn (immediate)
6965 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6966 // cmn (register)
6967 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006968 // cmp (immediate)
6969 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6970 // cmp (register)
6971 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006972 // asr (immediate)
6973 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006974 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006975 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006976 // lsl (immediate)
6977 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6978 // lsl (register)
6979 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6980 // lsr (immediate)
6981 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6982 // lsr (register)
6983 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006984 // rrx is a special case encoding of ror (immediate)
6985 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6986 // ror (immediate)
6987 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6988 // ror (register)
6989 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006990
6991 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006992 // Load instructions
6993 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006994 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006995 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006996 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006997 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006998 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006999 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00007000 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
7001 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00007002
7003 //----------------------------------------------------------------------
7004 // Store instructions
7005 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00007006 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007007 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00007008 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00007009 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
7010 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00007011
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007012
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007013 };
7014 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
7015
7016 for (size_t i=0; i<k_num_arm_opcodes; ++i)
7017 {
7018 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
7019 return &g_arm_opcodes[i];
7020 }
7021 return NULL;
7022}
Greg Clayton64c84432011-01-21 22:02:52 +00007023
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007024
7025EmulateInstructionARM::ARMOpcode*
7026EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00007027{
Johnny Chenfdd179e2011-01-31 20:09:28 +00007028
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007029 static ARMOpcode
7030 g_thumb_opcodes[] =
7031 {
7032 //----------------------------------------------------------------------
7033 // Prologue instructions
7034 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00007035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007036 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00007037 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
7038 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
7039 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00007040
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007041 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00007042 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007043 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00007044 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007045 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00007046 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00007047
Johnny Chen864a8e82011-02-18 00:07:39 +00007048 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00007049 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00007050
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007051 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00007052 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007053 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00007054 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
7055 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007056
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007057 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00007058 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
7059 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007060
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007061 //----------------------------------------------------------------------
7062 // Epilogue instructions
7063 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00007064
Johnny Chen864a8e82011-02-18 00:07:39 +00007065 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00007066 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
7067 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
7068 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00007069 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
7070 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007071
7072 //----------------------------------------------------------------------
7073 // Supervisor Call (previously Software Interrupt)
7074 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00007075 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
7076
7077 //----------------------------------------------------------------------
7078 // If Then makes up to four following instructions conditional.
7079 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00007080 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
7081
7082 //----------------------------------------------------------------------
7083 // Branch instructions
7084 //----------------------------------------------------------------------
7085 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
7086 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
7087 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00007088 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007089 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00007090 // J1 == J2 == 1
7091 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
7092 // J1 == J2 == 1
7093 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
7094 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00007095 // for example, "bx lr"
7096 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00007097 // compare and branch
7098 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00007099 // table branch byte
7100 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
7101 // table branch halfword
7102 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007103
7104 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00007105 // Data-processing instructions
7106 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00007107 // adc (immediate)
7108 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
7109 // adc (register)
7110 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
7111 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
7112 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00007113 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007114 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00007115 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00007116 // adr
7117 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
7118 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
7119 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007120 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007121 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007122 // and (register)
7123 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
7124 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00007125 // eor (immediate)
7126 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
7127 // eor (register)
7128 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
7129 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007130 // orr (immediate)
7131 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
7132 // orr (register)
7133 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
7134 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00007135 // rsb (immediate)
7136 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
7137 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
7138 // rsb (register)
7139 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00007140 // sbc (immediate)
7141 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
7142 // sbc (register)
7143 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
7144 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007145 // sub (immediate, Thumb)
7146 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
7147 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
7148 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
7149 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007150 // sub (sp minus immediate)
7151 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
7152 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00007153 // teq (immediate)
7154 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
7155 // teq (register)
7156 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00007157 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00007158 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00007159 // tst (register)
7160 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
7161 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
7162
Johnny Chen7c5234d2011-02-18 23:41:11 +00007163
Johnny Chen338bf542011-02-10 19:29:03 +00007164 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00007165 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00007166 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00007167 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007168 // mov{s}<c>.w <Rd>, <Rm>
7169 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00007170 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00007171 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
7172 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00007173 // mvn (immediate)
7174 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
7175 // mvn (register)
7176 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
7177 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007178 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00007179 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007180 // cmn (register)
7181 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007182 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007183 // cmp (immediate)
7184 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007185 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007186 // cmp (register) (Rn and Rm both from r0-r7)
7187 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
7188 // cmp (register) (Rn and Rm not both from r0-r7)
7189 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007190 // asr (immediate)
7191 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00007192 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00007193 // asr (register)
7194 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
7195 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007196 // lsl (immediate)
7197 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
7198 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
7199 // lsl (register)
7200 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
7201 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
7202 // lsr (immediate)
7203 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
7204 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
7205 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00007206 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007207 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007208 // rrx is a special case encoding of ror (immediate)
7209 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
7210 // ror (immediate)
7211 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
7212 // ror (register)
7213 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
7214 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007215
7216 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007217 // Load instructions
7218 //----------------------------------------------------------------------
7219 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00007220 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00007221 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00007222 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
7223 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00007224 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00007225 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
7226 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00007227 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
7228 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
7229 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00007230 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00007231 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
7232 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00007233
7234 //----------------------------------------------------------------------
7235 // Store instructions
7236 //----------------------------------------------------------------------
7237 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007238 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00007239 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00007240 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
7241 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
7242 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
7243 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
7244 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
7245 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
7246 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
7247 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
7248 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007249 };
7250
7251 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
7252 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
7253 {
7254 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
7255 return &g_thumb_opcodes[i];
7256 }
7257 return NULL;
7258}
Greg Clayton64c84432011-01-21 22:02:52 +00007259
Greg Clayton31e2a382011-01-30 20:03:56 +00007260bool
Greg Clayton395fc332011-02-15 21:59:32 +00007261EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00007262{
7263 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00007264 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00007265 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00007266 {
Greg Clayton395fc332011-02-15 21:59:32 +00007267 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
7268 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
7269 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
7270 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
7271 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
7272 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
7273 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
7274 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
7275 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
7276 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00007277 }
7278 return m_arm_isa != 0;
7279}
7280
7281
Greg Clayton64c84432011-01-21 22:02:52 +00007282bool
7283EmulateInstructionARM::ReadInstruction ()
7284{
7285 bool success = false;
7286 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
7287 if (success)
7288 {
7289 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
7290 if (success)
7291 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00007292 Context read_inst_context;
7293 read_inst_context.type = eContextReadOpcode;
7294 read_inst_context.SetNoArgs ();
7295
Greg Clayton64c84432011-01-21 22:02:52 +00007296 if (m_inst_cpsr & MASK_CPSR_T)
7297 {
7298 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007299 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007300
7301 if (success)
7302 {
7303 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
7304 {
7305 m_inst.opcode_type = eOpcode16;
7306 m_inst.opcode.inst16 = thumb_opcode;
7307 }
7308 else
7309 {
7310 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007311 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007312 }
7313 }
7314 }
7315 else
7316 {
7317 m_inst_mode = eModeARM;
7318 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007319 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007320 }
7321 }
7322 }
7323 if (!success)
7324 {
7325 m_inst_mode = eModeInvalid;
7326 m_inst_pc = LLDB_INVALID_ADDRESS;
7327 }
7328 return success;
7329}
7330
Johnny Chenee9b1f72011-02-09 01:00:31 +00007331uint32_t
7332EmulateInstructionARM::ArchVersion ()
7333{
7334 return m_arm_isa;
7335}
7336
Greg Clayton64c84432011-01-21 22:02:52 +00007337bool
7338EmulateInstructionARM::ConditionPassed ()
7339{
7340 if (m_inst_cpsr == 0)
7341 return false;
7342
7343 const uint32_t cond = CurrentCond ();
7344
7345 if (cond == UINT32_MAX)
7346 return false;
7347
7348 bool result = false;
7349 switch (UnsignedBits(cond, 3, 1))
7350 {
7351 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
7352 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
7353 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
7354 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
7355 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
7356 case 5:
7357 {
7358 bool n = (m_inst_cpsr & MASK_CPSR_N);
7359 bool v = (m_inst_cpsr & MASK_CPSR_V);
7360 result = n == v;
7361 }
7362 break;
7363 case 6:
7364 {
7365 bool n = (m_inst_cpsr & MASK_CPSR_N);
7366 bool v = (m_inst_cpsr & MASK_CPSR_V);
7367 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
7368 }
7369 break;
7370 case 7:
7371 result = true;
7372 break;
7373 }
7374
7375 if (cond & 1)
7376 result = !result;
7377 return result;
7378}
7379
Johnny Chen9ee056b2011-02-08 00:06:35 +00007380uint32_t
7381EmulateInstructionARM::CurrentCond ()
7382{
7383 switch (m_inst_mode)
7384 {
7385 default:
7386 case eModeInvalid:
7387 break;
7388
7389 case eModeARM:
7390 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
7391
7392 case eModeThumb:
7393 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
7394 // 'cond' field of the encoding.
7395 if (m_inst.opcode_type == eOpcode16 &&
7396 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
7397 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
7398 {
7399 return Bits32(m_inst.opcode.inst16, 11, 7);
7400 }
7401 else if (m_inst.opcode_type == eOpcode32 &&
7402 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
7403 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
7404 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
7405 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
7406 {
7407 return Bits32(m_inst.opcode.inst32, 25, 22);
7408 }
7409
7410 return m_it_session.GetCond();
7411 }
7412 return UINT32_MAX; // Return invalid value
7413}
7414
Johnny Chen9ee056b2011-02-08 00:06:35 +00007415bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00007416EmulateInstructionARM::InITBlock()
7417{
7418 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
7419}
7420
7421bool
7422EmulateInstructionARM::LastInITBlock()
7423{
7424 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
7425}
7426
7427bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00007428EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
7429{
7430 addr_t target;
7431
Johnny Chenee9b1f72011-02-09 01:00:31 +00007432 // Check the current instruction set.
7433 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007434 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007435 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00007436 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007437
Johnny Chen9ee056b2011-02-08 00:06:35 +00007438 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007439 return false;
7440
7441 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007442}
7443
7444// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
7445bool
Johnny Chen668b4512011-02-15 21:08:58 +00007446EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007447{
7448 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00007449 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
7450 // we want to record it and issue a WriteRegister callback so the clients
7451 // can track the mode changes accordingly.
7452 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007453
7454 if (BitIsSet(addr, 0))
7455 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007456 if (CurrentInstrSet() != eModeThumb)
7457 {
7458 SelectInstrSet(eModeThumb);
7459 cpsr_changed = true;
7460 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007461 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00007462 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007463 }
7464 else if (BitIsClear(addr, 1))
7465 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007466 if (CurrentInstrSet() != eModeARM)
7467 {
7468 SelectInstrSet(eModeARM);
7469 cpsr_changed = true;
7470 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007471 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00007472 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007473 }
7474 else
7475 return false; // address<1:0> == '10' => UNPREDICTABLE
7476
Johnny Chen0f309db2011-02-09 19:11:32 +00007477 if (cpsr_changed)
7478 {
Johnny Chen558133b2011-02-09 23:59:17 +00007479 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00007480 return false;
7481 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007482 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007483 return false;
7484
7485 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007486}
Greg Clayton64c84432011-01-21 22:02:52 +00007487
Johnny Chenee9b1f72011-02-09 01:00:31 +00007488// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
7489bool
Johnny Chen668b4512011-02-15 21:08:58 +00007490EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00007491{
7492 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00007493 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00007494 else
7495 return BranchWritePC((const Context)context, addr);
7496}
7497
Johnny Chen26863dc2011-02-09 23:43:29 +00007498// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
7499bool
Johnny Chen668b4512011-02-15 21:08:58 +00007500EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00007501{
7502 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00007503 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00007504 else
7505 return BranchWritePC((const Context)context, addr);
7506}
7507
Johnny Chenee9b1f72011-02-09 01:00:31 +00007508EmulateInstructionARM::Mode
7509EmulateInstructionARM::CurrentInstrSet ()
7510{
7511 return m_inst_mode;
7512}
7513
7514// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00007515// ReadInstruction() is performed. This function has a side effect of updating
7516// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00007517bool
7518EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
7519{
Johnny Chen558133b2011-02-09 23:59:17 +00007520 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007521 switch (arm_or_thumb)
7522 {
7523 default:
7524 return false;
7525 eModeARM:
7526 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007527 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007528 break;
7529 eModeThumb:
7530 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007531 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007532 break;
7533 }
7534 return true;
7535}
7536
Johnny Chenef21b592011-02-10 01:52:38 +00007537// This function returns TRUE if the processor currently provides support for
7538// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
7539// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
7540bool
7541EmulateInstructionARM::UnalignedSupport()
7542{
7543 return (ArchVersion() >= ARMv7);
7544}
7545
Johnny Chenbf6ad172011-02-11 01:29:53 +00007546// The main addition and subtraction instructions can produce status information
7547// about both unsigned carry and signed overflow conditions. This status
7548// information can be used to synthesize multi-word additions and subtractions.
7549EmulateInstructionARM::AddWithCarryResult
7550EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
7551{
7552 uint32_t result;
7553 uint8_t carry_out;
7554 uint8_t overflow;
7555
7556 uint64_t unsigned_sum = x + y + carry_in;
7557 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
7558
7559 result = UnsignedBits(unsigned_sum, 31, 0);
7560 carry_out = (result == unsigned_sum ? 0 : 1);
7561 overflow = ((int32_t)result == signed_sum ? 0 : 1);
7562
7563 AddWithCarryResult res = { result, carry_out, overflow };
7564 return res;
7565}
7566
Johnny Chen157b9592011-02-18 21:13:05 +00007567uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00007568EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00007569{
Johnny Chene39f22d2011-02-19 01:36:13 +00007570 uint32_t reg_kind, reg_num;
7571 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00007572 {
Johnny Chene39f22d2011-02-19 01:36:13 +00007573 case SP_REG:
7574 reg_kind = eRegisterKindGeneric;
7575 reg_num = LLDB_REGNUM_GENERIC_SP;
7576 break;
7577 case LR_REG:
7578 reg_kind = eRegisterKindGeneric;
7579 reg_num = LLDB_REGNUM_GENERIC_RA;
7580 break;
7581 case PC_REG:
7582 reg_kind = eRegisterKindGeneric;
7583 reg_num = LLDB_REGNUM_GENERIC_PC;
7584 break;
7585 default:
7586 if (0 <= num && num < SP_REG)
7587 {
7588 reg_kind = eRegisterKindDWARF;
7589 reg_num = dwarf_r0 + num;
7590 }
Johnny Chen157b9592011-02-18 21:13:05 +00007591 else
Johnny Chene39f22d2011-02-19 01:36:13 +00007592 {
7593 assert(0 && "Invalid register number");
7594 *success = false;
7595 return ~0u;
7596 }
7597 break;
Johnny Chen157b9592011-02-18 21:13:05 +00007598 }
Johnny Chene39f22d2011-02-19 01:36:13 +00007599
7600 // Read our register.
7601 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
7602
7603 // When executing an ARM instruction , PC reads as the address of the current
7604 // instruction plus 8.
7605 // When executing a Thumb instruction , PC reads as the address of the current
7606 // instruction plus 4.
7607 if (num == 15)
7608 {
7609 if (CurrentInstrSet() == eModeARM)
7610 val += 8;
7611 else
7612 val += 4;
7613 }
Johnny Chen157b9592011-02-18 21:13:05 +00007614
7615 return val;
7616}
7617
Johnny Chenca67d1c2011-02-17 01:35:27 +00007618// Write the result to the ARM core register Rd, and optionally update the
7619// condition flags based on the result.
7620//
7621// This helper method tries to encapsulate the following pseudocode from the
7622// ARM Architecture Reference Manual:
7623//
7624// if d == 15 then // Can only occur for encoding A1
7625// ALUWritePC(result); // setflags is always FALSE here
7626// else
7627// R[d] = result;
7628// if setflags then
7629// APSR.N = result<31>;
7630// APSR.Z = IsZeroBit(result);
7631// APSR.C = carry;
7632// // APSR.V unchanged
7633//
7634// In the above case, the API client does not pass in the overflow arg, which
7635// defaults to ~0u.
7636bool
Johnny Chen10530c22011-02-17 22:37:12 +00007637EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
7638 const uint32_t result,
7639 const uint32_t Rd,
7640 bool setflags,
7641 const uint32_t carry,
7642 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00007643{
7644 if (Rd == 15)
7645 {
7646 if (!ALUWritePC (context, result))
7647 return false;
7648 }
7649 else
7650 {
Johnny Chena695f952011-02-23 21:24:25 +00007651 uint32_t reg_kind, reg_num;
7652 switch (Rd)
7653 {
7654 case SP_REG:
7655 reg_kind = eRegisterKindGeneric;
7656 reg_num = LLDB_REGNUM_GENERIC_SP;
7657 break;
7658 case LR_REG:
7659 reg_kind = eRegisterKindGeneric;
7660 reg_num = LLDB_REGNUM_GENERIC_RA;
7661 break;
7662 default:
7663 reg_kind = eRegisterKindDWARF;
7664 reg_num = dwarf_r0 + Rd;
7665 }
7666 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00007667 return false;
7668 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00007669 return WriteFlags (context, result, carry, overflow);
7670 }
7671 return true;
7672}
7673
7674// This helper method tries to encapsulate the following pseudocode from the
7675// ARM Architecture Reference Manual:
7676//
7677// APSR.N = result<31>;
7678// APSR.Z = IsZeroBit(result);
7679// APSR.C = carry;
7680// APSR.V = overflow
7681//
7682// Default arguments can be specified for carry and overflow parameters, which means
7683// not to update the respective flags.
7684bool
7685EmulateInstructionARM::WriteFlags (Context &context,
7686 const uint32_t result,
7687 const uint32_t carry,
7688 const uint32_t overflow)
7689{
7690 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00007691 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
7692 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00007693 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007694 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00007695 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007696 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00007697 if (m_new_inst_cpsr != m_inst_cpsr)
7698 {
7699 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
7700 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00007701 }
7702 return true;
7703}
7704
Greg Clayton64c84432011-01-21 22:02:52 +00007705bool
7706EmulateInstructionARM::EvaluateInstruction ()
7707{
Johnny Chenc315f862011-02-05 00:46:10 +00007708 // Advance the ITSTATE bits to their values for the next instruction.
7709 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
7710 m_it_session.ITAdvance();
7711
Greg Clayton64c84432011-01-21 22:02:52 +00007712 return false;
7713}