blob: 2c090c09f642098f8326c888db8c351cdf2c2e79 [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.
27#define APSR_C Bit32(m_inst_cpsr, CPSR_C)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V)
29
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:
1003 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1004 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 Chen4c0e0bc2011-01-25 22:45:28 +00001410// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001411bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001412EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001413{
1414#if 0
1415 // ARM pseudo code...
1416 if (ConditionPassed())
1417 {
1418 EncodingSpecificOperations();
1419 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1420 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001421 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001422 else
1423 R[d] = result;
1424 if setflags then
1425 APSR.N = result<31>;
1426 APSR.Z = IsZeroBit(result);
1427 APSR.C = carry;
1428 APSR.V = overflow;
1429 }
1430#endif
1431
1432 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001433 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001434 if (!success)
1435 return false;
1436
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001437 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001438 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001439 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001440 if (!success)
1441 return false;
1442 uint32_t imm32;
1443 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001444 case eEncodingT1:
1445 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001446 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001447 case eEncodingT2:
1448 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1449 break;
1450 case eEncodingT3:
1451 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1452 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001453 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001454 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001455 break;
1456 default:
1457 return false;
1458 }
1459 addr_t sp_offset = imm32;
1460 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1461
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001462 EmulateInstruction::Context context;
1463 context.type = EmulateInstruction::eContextAdjustStackPointer;
1464 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001465
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001466 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001467 return false;
1468 }
1469 return true;
1470}
1471
Johnny Chen08c25e82011-01-31 18:02:28 +00001472// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001473bool
1474EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001475{
1476#if 0
1477 // ARM pseudo code...
1478 if (ConditionPassed())
1479 {
1480 EncodingSpecificOperations();
1481 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1482 address = if index then offset_addr else R[n];
1483 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1484 if wback then R[n] = offset_addr;
1485 }
1486#endif
1487
1488 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001489 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001490 if (!success)
1491 return false;
1492
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001493 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001494 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001495 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001496 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001497 if (!success)
1498 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001499 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001500 uint32_t imm12;
1501 switch (encoding) {
1502 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001503 Rt = Bits32(opcode, 15, 12);
1504 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001505 break;
1506 default:
1507 return false;
1508 }
1509 addr_t sp_offset = imm12;
1510 addr_t addr = sp - sp_offset;
1511
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001512 EmulateInstruction::Context context;
1513 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1514 Register dwarf_reg;
1515 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001516 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001517 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001518 dwarf_reg.num = dwarf_r0 + Rt;
1519 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001520 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001521 if (!success)
1522 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001523 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001524 return false;
1525 }
1526 else
1527 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001528 dwarf_reg.num = dwarf_pc;
1529 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001530 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001531 if (!success)
1532 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001533 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001534 return false;
1535 }
1536
1537 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001538 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001539
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001540 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001541 return false;
1542 }
1543 return true;
1544}
1545
Johnny Chen08c25e82011-01-31 18:02:28 +00001546// Vector Push stores multiple extension registers to the stack.
1547// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001548bool
1549EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001550{
1551#if 0
1552 // ARM pseudo code...
1553 if (ConditionPassed())
1554 {
1555 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1556 address = SP - imm32;
1557 SP = SP - imm32;
1558 if single_regs then
1559 for r = 0 to regs-1
1560 MemA[address,4] = S[d+r]; address = address+4;
1561 else
1562 for r = 0 to regs-1
1563 // Store as two word-aligned words in the correct order for current endianness.
1564 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1565 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1566 address = address+8;
1567 }
1568#endif
1569
1570 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001571 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001572 if (!success)
1573 return false;
1574
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001575 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001576 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001577 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001578 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001579 if (!success)
1580 return false;
1581 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001582 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001583 uint32_t imm32; // stack offset
1584 uint32_t regs; // number of registers
1585 switch (encoding) {
1586 case eEncodingT1:
1587 case eEncodingA1:
1588 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001589 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001590 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1591 // If UInt(imm8) is odd, see "FSTMX".
1592 regs = Bits32(opcode, 7, 0) / 2;
1593 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1594 if (regs == 0 || regs > 16 || (d + regs) > 32)
1595 return false;
1596 break;
1597 case eEncodingT2:
1598 case eEncodingA2:
1599 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001600 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001601 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1602 regs = Bits32(opcode, 7, 0);
1603 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1604 if (regs == 0 || regs > 16 || (d + regs) > 32)
1605 return false;
1606 break;
1607 default:
1608 return false;
1609 }
1610 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1611 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1612 addr_t sp_offset = imm32;
1613 addr_t addr = sp - sp_offset;
1614 uint32_t i;
1615
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001616 EmulateInstruction::Context context;
1617 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1618 Register dwarf_reg;
1619 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001620 for (i=d; i<regs; ++i)
1621 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001622 dwarf_reg.num = start_reg + i;
1623 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001624 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001625 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001626 if (!success)
1627 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001628 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001629 return false;
1630 addr += reg_byte_size;
1631 }
1632
1633 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001634 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001635
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001636 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001637 return false;
1638 }
1639 return true;
1640}
1641
Johnny Chen587a0a42011-02-01 18:35:28 +00001642// Vector Pop loads multiple extension registers from the stack.
1643// It also updates SP to point just above the loaded data.
1644bool
1645EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1646{
1647#if 0
1648 // ARM pseudo code...
1649 if (ConditionPassed())
1650 {
1651 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1652 address = SP;
1653 SP = SP + imm32;
1654 if single_regs then
1655 for r = 0 to regs-1
1656 S[d+r] = MemA[address,4]; address = address+4;
1657 else
1658 for r = 0 to regs-1
1659 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1660 // Combine the word-aligned words in the correct order for current endianness.
1661 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1662 }
1663#endif
1664
1665 bool success = false;
1666 const uint32_t opcode = OpcodeAsUnsigned (&success);
1667 if (!success)
1668 return false;
1669
1670 if (ConditionPassed())
1671 {
1672 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001673 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001674 if (!success)
1675 return false;
1676 bool single_regs;
1677 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1678 uint32_t imm32; // stack offset
1679 uint32_t regs; // number of registers
1680 switch (encoding) {
1681 case eEncodingT1:
1682 case eEncodingA1:
1683 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001684 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001685 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1686 // If UInt(imm8) is odd, see "FLDMX".
1687 regs = Bits32(opcode, 7, 0) / 2;
1688 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1689 if (regs == 0 || regs > 16 || (d + regs) > 32)
1690 return false;
1691 break;
1692 case eEncodingT2:
1693 case eEncodingA2:
1694 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001695 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001696 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1697 regs = Bits32(opcode, 7, 0);
1698 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1699 if (regs == 0 || regs > 16 || (d + regs) > 32)
1700 return false;
1701 break;
1702 default:
1703 return false;
1704 }
1705 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1706 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1707 addr_t sp_offset = imm32;
1708 addr_t addr = sp;
1709 uint32_t i;
1710 uint64_t data; // uint64_t to accomodate 64-bit registers.
1711
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001712 EmulateInstruction::Context context;
1713 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1714 Register dwarf_reg;
1715 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001716 for (i=d; i<regs; ++i)
1717 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001718 dwarf_reg.num = start_reg + i;
1719 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001720 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001721 if (!success)
1722 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001723 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001724 return false;
1725 addr += reg_byte_size;
1726 }
1727
1728 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001729 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001730
1731 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1732 return false;
1733 }
1734 return true;
1735}
1736
Johnny Chenb77be412011-02-04 00:40:18 +00001737// SVC (previously SWI)
1738bool
1739EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1740{
1741#if 0
1742 // ARM pseudo code...
1743 if (ConditionPassed())
1744 {
1745 EncodingSpecificOperations();
1746 CallSupervisor();
1747 }
1748#endif
1749
1750 bool success = false;
1751 const uint32_t opcode = OpcodeAsUnsigned (&success);
1752 if (!success)
1753 return false;
1754
1755 if (ConditionPassed())
1756 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001757 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001758 addr_t lr; // next instruction address
1759 if (!success)
1760 return false;
1761 uint32_t imm32; // the immediate constant
1762 uint32_t mode; // ARM or Thumb mode
1763 switch (encoding) {
1764 case eEncodingT1:
1765 lr = (pc + 2) | 1u; // return address
1766 imm32 = Bits32(opcode, 7, 0);
1767 mode = eModeThumb;
1768 break;
1769 case eEncodingA1:
1770 lr = pc + 4; // return address
1771 imm32 = Bits32(opcode, 23, 0);
1772 mode = eModeARM;
1773 break;
1774 default:
1775 return false;
1776 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001777
1778 EmulateInstruction::Context context;
1779 context.type = EmulateInstruction::eContextSupervisorCall;
1780 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001781 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1782 return false;
1783 }
1784 return true;
1785}
1786
Johnny Chenc315f862011-02-05 00:46:10 +00001787// If Then makes up to four following instructions (the IT block) conditional.
1788bool
1789EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1790{
1791#if 0
1792 // ARM pseudo code...
1793 EncodingSpecificOperations();
1794 ITSTATE.IT<7:0> = firstcond:mask;
1795#endif
1796
1797 bool success = false;
1798 const uint32_t opcode = OpcodeAsUnsigned (&success);
1799 if (!success)
1800 return false;
1801
1802 m_it_session.InitIT(Bits32(opcode, 7, 0));
1803 return true;
1804}
1805
Johnny Chen3b620b32011-02-07 20:11:47 +00001806// Branch causes a branch to a target address.
1807bool
1808EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1809{
1810#if 0
1811 // ARM pseudo code...
1812 if (ConditionPassed())
1813 {
1814 EncodingSpecificOperations();
1815 BranchWritePC(PC + imm32);
1816 }
1817#endif
1818
1819 bool success = false;
1820 const uint32_t opcode = OpcodeAsUnsigned (&success);
1821 if (!success)
1822 return false;
1823
Johnny Chen9ee056b2011-02-08 00:06:35 +00001824 if (ConditionPassed())
1825 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001826 EmulateInstruction::Context context;
1827 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001828 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001829 if (!success)
1830 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001831 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001832 int32_t imm32; // PC-relative offset
1833 switch (encoding) {
1834 case eEncodingT1:
1835 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1836 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001837 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001838 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001839 break;
1840 case eEncodingT2:
1841 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001842 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001843 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001844 break;
1845 case eEncodingT3:
1846 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1847 {
Johnny Chenbd599902011-02-10 21:39:01 +00001848 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001849 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001850 uint32_t J1 = Bit32(opcode, 13);
1851 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001852 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001853 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001854 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001855 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001856 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001857 break;
1858 }
1859 case eEncodingT4:
1860 {
Johnny Chenbd599902011-02-10 21:39:01 +00001861 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001862 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001863 uint32_t J1 = Bit32(opcode, 13);
1864 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001865 uint32_t imm11 = Bits32(opcode, 10, 0);
1866 uint32_t I1 = !(J1 ^ S);
1867 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001868 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001869 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001870 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001871 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001872 break;
1873 }
1874 case eEncodingA1:
1875 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001876 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001877 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001878 break;
1879 default:
1880 return false;
1881 }
1882 if (!BranchWritePC(context, target))
1883 return false;
1884 }
1885 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001886}
1887
Johnny Chen53ebab72011-02-08 23:21:57 +00001888// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1889// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1890// CBNZ, CBZ
1891bool
1892EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1893{
1894#if 0
1895 // ARM pseudo code...
1896 EncodingSpecificOperations();
1897 if nonzero ^ IsZero(R[n]) then
1898 BranchWritePC(PC + imm32);
1899#endif
1900
1901 bool success = false;
1902 const uint32_t opcode = OpcodeAsUnsigned (&success);
1903 if (!success)
1904 return false;
1905
1906 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00001907 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001908 if (!success)
1909 return false;
1910
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001911 EmulateInstruction::Context context;
1912 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001913 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001914 if (!success)
1915 return false;
1916
1917 addr_t target; // target address
1918 uint32_t imm32; // PC-relative offset to branch forward
1919 bool nonzero;
1920 switch (encoding) {
1921 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001922 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001923 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00001924 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001925 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001926 break;
1927 default:
1928 return false;
1929 }
1930 if (nonzero ^ (reg_val == 0))
1931 if (!BranchWritePC(context, target))
1932 return false;
1933
1934 return true;
1935}
1936
Johnny Chen60299ec2011-02-17 19:34:27 +00001937// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1938// A base register provides a pointer to the table, and a second register supplies an index into the table.
1939// The branch length is twice the value of the byte returned from the table.
1940//
1941// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1942// A base register provides a pointer to the table, and a second register supplies an index into the table.
1943// The branch length is twice the value of the halfword returned from the table.
1944// TBB, TBH
1945bool
1946EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1947{
1948#if 0
1949 // ARM pseudo code...
1950 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1951 if is_tbh then
1952 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1953 else
1954 halfwords = UInt(MemU[R[n]+R[m], 1]);
1955 BranchWritePC(PC + 2*halfwords);
1956#endif
1957
1958 bool success = false;
1959 const uint32_t opcode = OpcodeAsUnsigned (&success);
1960 if (!success)
1961 return false;
1962
1963 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1964 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1965 bool is_tbh; // true if table branch halfword
1966 switch (encoding) {
1967 case eEncodingT1:
1968 Rn = Bits32(opcode, 19, 16);
1969 Rm = Bits32(opcode, 3, 0);
1970 is_tbh = BitIsSet(opcode, 4);
1971 if (Rn == 13 || BadReg(Rm))
1972 return false;
1973 if (InITBlock() && !LastInITBlock())
1974 return false;
1975 break;
1976 default:
1977 return false;
1978 }
1979
1980 // Read the address of the table from the operand register Rn.
1981 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00001982 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001983 if (!success)
1984 return false;
1985
1986 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00001987 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001988 if (!success)
1989 return false;
1990
1991 // the offsetted table address
1992 addr_t addr = base + (is_tbh ? index*2 : index);
1993
1994 // PC-relative offset to branch forward
1995 EmulateInstruction::Context context;
1996 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001997 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001998 if (!success)
1999 return false;
2000
Johnny Chene39f22d2011-02-19 01:36:13 +00002001 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002002 if (!success)
2003 return false;
2004
2005 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002006 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002007 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2008 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2009
2010 if (!BranchWritePC(context, target))
2011 return false;
2012
2013 return true;
2014}
2015
Johnny Chen8fa20592011-02-18 01:22:22 +00002016// This instruction adds an immediate value to a register value, and writes the result to the destination
2017// register. It can optionally update the condition flags based on the result.
2018bool
2019EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2020{
2021#if 0
2022 // ARM pseudo code...
2023 if ConditionPassed() then
2024 EncodingSpecificOperations();
2025 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2026 if d == 15 then
2027 ALUWritePC(result); // setflags is always FALSE here
2028 else
2029 R[d] = result;
2030 if setflags then
2031 APSR.N = result<31>;
2032 APSR.Z = IsZeroBit(result);
2033 APSR.C = carry;
2034 APSR.V = overflow;
2035#endif
2036
2037 bool success = false;
2038 const uint32_t opcode = OpcodeAsUnsigned (&success);
2039 if (!success)
2040 return false;
2041
2042 if (ConditionPassed())
2043 {
2044 uint32_t Rd, Rn;
2045 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2046 bool setflags;
2047 switch (encoding)
2048 {
2049 case eEncodingA1:
2050 Rd = Bits32(opcode, 15, 12);
2051 Rn = Bits32(opcode, 19, 16);
2052 setflags = BitIsSet(opcode, 20);
2053 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2054 break;
2055 default:
2056 return false;
2057 }
2058
Johnny Chen8fa20592011-02-18 01:22:22 +00002059 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002060 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002061 if (!success)
2062 return false;
2063
2064 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2065
2066 EmulateInstruction::Context context;
2067 context.type = EmulateInstruction::eContextImmediate;
2068 context.SetNoArgs ();
2069
2070 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2071 return false;
2072 }
2073 return true;
2074}
2075
Johnny Chend761dcf2011-02-17 22:03:29 +00002076// This instruction adds a register value and an optionally-shifted register value, and writes the result
2077// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002078bool
Johnny Chen9f687722011-02-18 00:02:28 +00002079EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002080{
2081#if 0
2082 // ARM pseudo code...
2083 if ConditionPassed() then
2084 EncodingSpecificOperations();
2085 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2086 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2087 if d == 15 then
2088 ALUWritePC(result); // setflags is always FALSE here
2089 else
2090 R[d] = result;
2091 if setflags then
2092 APSR.N = result<31>;
2093 APSR.Z = IsZeroBit(result);
2094 APSR.C = carry;
2095 APSR.V = overflow;
2096#endif
2097
2098 bool success = false;
2099 const uint32_t opcode = OpcodeAsUnsigned (&success);
2100 if (!success)
2101 return false;
2102
2103 if (ConditionPassed())
2104 {
2105 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002106 ARM_ShifterType shift_t;
2107 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002108 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002109 switch (encoding)
2110 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002111 case eEncodingT1:
2112 Rd = Bits32(opcode, 2, 0);
2113 Rn = Bits32(opcode, 5, 3);
2114 Rm = Bits32(opcode, 8, 6);
2115 setflags = !InITBlock();
2116 shift_t = SRType_LSL;
2117 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002118 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002119 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002120 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002121 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002122 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002123 shift_t = SRType_LSL;
2124 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002125 if (Rn == 15 && Rm == 15)
2126 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002127 if (Rd == 15 && InITBlock() && !LastInITBlock())
2128 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002129 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002130 case eEncodingA1:
2131 Rd = Bits32(opcode, 15, 12);
2132 Rn = Bits32(opcode, 19, 16);
2133 Rm = Bits32(opcode, 3, 0);
2134 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002135 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002136 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002137 default:
2138 return false;
2139 }
2140
Johnny Chen26863dc2011-02-09 23:43:29 +00002141 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002142 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002143 if (!success)
2144 return false;
2145
2146 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002147 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002148 if (!success)
2149 return false;
2150
Johnny Chene97c0d52011-02-18 19:32:20 +00002151 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002152 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002153
2154 EmulateInstruction::Context context;
2155 context.type = EmulateInstruction::eContextImmediate;
2156 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002157
Johnny Chen10530c22011-02-17 22:37:12 +00002158 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002159 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002160 }
2161 return true;
2162}
2163
Johnny Chen34075cb2011-02-22 01:56:31 +00002164// Compare Negative (immediate) adds a register value and an immediate value.
2165// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002166bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002167EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2168{
2169#if 0
2170 // ARM pseudo code...
2171 if ConditionPassed() then
2172 EncodingSpecificOperations();
2173 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2174 APSR.N = result<31>;
2175 APSR.Z = IsZeroBit(result);
2176 APSR.C = carry;
2177 APSR.V = overflow;
2178#endif
2179
2180 bool success = false;
2181 const uint32_t opcode = OpcodeAsUnsigned (&success);
2182 if (!success)
2183 return false;
2184
2185 uint32_t Rn; // the first operand
2186 uint32_t imm32; // the immediate value to be compared with
2187 switch (encoding) {
2188 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002189 Rn = Bits32(opcode, 19, 16);
2190 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2191 if (Rn == 15)
2192 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002193 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002194 case eEncodingA1:
2195 Rn = Bits32(opcode, 19, 16);
2196 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2197 break;
2198 default:
2199 return false;
2200 }
2201 // Read the register value from the operand register Rn.
2202 uint32_t reg_val = ReadCoreReg(Rn, &success);
2203 if (!success)
2204 return false;
2205
Johnny Chen078fbc62011-02-22 19:48:22 +00002206 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002207
2208 EmulateInstruction::Context context;
2209 context.type = EmulateInstruction::eContextImmediate;
2210 context.SetNoArgs ();
2211 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2212 return false;
2213
2214 return true;
2215}
2216
2217// Compare Negative (register) adds a register value and an optionally-shifted register value.
2218// It updates the condition flags based on the result, and discards the result.
2219bool
2220EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2221{
2222#if 0
2223 // ARM pseudo code...
2224 if ConditionPassed() then
2225 EncodingSpecificOperations();
2226 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2227 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2228 APSR.N = result<31>;
2229 APSR.Z = IsZeroBit(result);
2230 APSR.C = carry;
2231 APSR.V = overflow;
2232#endif
2233
2234 bool success = false;
2235 const uint32_t opcode = OpcodeAsUnsigned (&success);
2236 if (!success)
2237 return false;
2238
2239 uint32_t Rn; // the first operand
2240 uint32_t Rm; // the second operand
2241 ARM_ShifterType shift_t;
2242 uint32_t shift_n; // the shift applied to the value read from Rm
2243 switch (encoding) {
2244 case eEncodingT1:
2245 Rn = Bits32(opcode, 2, 0);
2246 Rm = Bits32(opcode, 5, 3);
2247 shift_t = SRType_LSL;
2248 shift_n = 0;
2249 break;
2250 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002251 Rn = Bits32(opcode, 19, 16);
2252 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002253 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002254 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2255 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002256 return false;
2257 break;
2258 case eEncodingA1:
2259 Rn = Bits32(opcode, 19, 16);
2260 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002261 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002262 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002263 default:
2264 return false;
2265 }
2266 // Read the register value from register Rn.
2267 uint32_t val1 = ReadCoreReg(Rn, &success);
2268 if (!success)
2269 return false;
2270
2271 // Read the register value from register Rm.
2272 uint32_t val2 = ReadCoreReg(Rm, &success);
2273 if (!success)
2274 return false;
2275
2276 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002277 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002278
2279 EmulateInstruction::Context context;
2280 context.type = EmulateInstruction::eContextImmediate;
2281 context.SetNoArgs();
2282 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2283 return false;
2284
2285 return true;
2286}
2287
2288// Compare (immediate) subtracts an immediate value from a register value.
2289// It updates the condition flags based on the result, and discards the result.
2290bool
2291EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002292{
2293#if 0
2294 // ARM pseudo code...
2295 if ConditionPassed() then
2296 EncodingSpecificOperations();
2297 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2298 APSR.N = result<31>;
2299 APSR.Z = IsZeroBit(result);
2300 APSR.C = carry;
2301 APSR.V = overflow;
2302#endif
2303
2304 bool success = false;
2305 const uint32_t opcode = OpcodeAsUnsigned (&success);
2306 if (!success)
2307 return false;
2308
2309 uint32_t Rn; // the first operand
2310 uint32_t imm32; // the immediate value to be compared with
2311 switch (encoding) {
2312 case eEncodingT1:
2313 Rn = Bits32(opcode, 10, 8);
2314 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002315 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002316 case eEncodingT2:
2317 Rn = Bits32(opcode, 19, 16);
2318 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2319 if (Rn == 15)
2320 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002321 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002322 case eEncodingA1:
2323 Rn = Bits32(opcode, 19, 16);
2324 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002325 break;
2326 default:
2327 return false;
2328 }
2329 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002330 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002331 if (!success)
2332 return false;
2333
Johnny Chen10530c22011-02-17 22:37:12 +00002334 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2335
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002336 EmulateInstruction::Context context;
2337 context.type = EmulateInstruction::eContextImmediate;
2338 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002339 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2340 return false;
2341
Johnny Chend4dc4442011-02-11 02:02:56 +00002342 return true;
2343}
2344
Johnny Chen34075cb2011-02-22 01:56:31 +00002345// Compare (register) subtracts an optionally-shifted register value from a register value.
2346// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002347bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002348EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002349{
2350#if 0
2351 // ARM pseudo code...
2352 if ConditionPassed() then
2353 EncodingSpecificOperations();
2354 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2355 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2356 APSR.N = result<31>;
2357 APSR.Z = IsZeroBit(result);
2358 APSR.C = carry;
2359 APSR.V = overflow;
2360#endif
2361
2362 bool success = false;
2363 const uint32_t opcode = OpcodeAsUnsigned (&success);
2364 if (!success)
2365 return false;
2366
2367 uint32_t Rn; // the first operand
2368 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002369 ARM_ShifterType shift_t;
2370 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002371 switch (encoding) {
2372 case eEncodingT1:
2373 Rn = Bits32(opcode, 2, 0);
2374 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002375 shift_t = SRType_LSL;
2376 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002377 break;
2378 case eEncodingT2:
2379 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2380 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002381 shift_t = SRType_LSL;
2382 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002383 if (Rn < 8 && Rm < 8)
2384 return false;
2385 if (Rn == 15 || Rm == 15)
2386 return false;
2387 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002388 case eEncodingA1:
2389 Rn = Bits32(opcode, 19, 16);
2390 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002391 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002392 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002393 default:
2394 return false;
2395 }
2396 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002397 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002398 if (!success)
2399 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002400
Johnny Chene4a4d302011-02-11 21:53:58 +00002401 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002402 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002403 if (!success)
2404 return false;
2405
Johnny Chen34075cb2011-02-22 01:56:31 +00002406 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2407 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002408
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002409 EmulateInstruction::Context context;
2410 context.type = EmulateInstruction::eContextImmediate;
2411 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002412 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2413 return false;
2414
Johnny Chene4a4d302011-02-11 21:53:58 +00002415 return true;
2416}
2417
Johnny Chen82f16aa2011-02-15 20:10:55 +00002418// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2419// shifting in copies of its sign bit, and writes the result to the destination register. It can
2420// optionally update the condition flags based on the result.
2421bool
2422EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2423{
2424#if 0
2425 // ARM pseudo code...
2426 if ConditionPassed() then
2427 EncodingSpecificOperations();
2428 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2429 if d == 15 then // Can only occur for ARM encoding
2430 ALUWritePC(result); // setflags is always FALSE here
2431 else
2432 R[d] = result;
2433 if setflags then
2434 APSR.N = result<31>;
2435 APSR.Z = IsZeroBit(result);
2436 APSR.C = carry;
2437 // APSR.V unchanged
2438#endif
2439
Johnny Chen41a0a152011-02-16 01:27:54 +00002440 return EmulateShiftImm(encoding, SRType_ASR);
2441}
2442
2443// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2444// shifting in copies of its sign bit, and writes the result to the destination register.
2445// The variable number of bits is read from the bottom byte of a register. It can optionally update
2446// the condition flags based on the result.
2447bool
2448EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2449{
2450#if 0
2451 // ARM pseudo code...
2452 if ConditionPassed() then
2453 EncodingSpecificOperations();
2454 shift_n = UInt(R[m]<7:0>);
2455 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2456 R[d] = result;
2457 if setflags then
2458 APSR.N = result<31>;
2459 APSR.Z = IsZeroBit(result);
2460 APSR.C = carry;
2461 // APSR.V unchanged
2462#endif
2463
2464 return EmulateShiftReg(encoding, SRType_ASR);
2465}
2466
2467// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2468// shifting in zeros, and writes the result to the destination register. It can optionally
2469// update the condition flags based on the result.
2470bool
2471EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2472{
2473#if 0
2474 // ARM pseudo code...
2475 if ConditionPassed() then
2476 EncodingSpecificOperations();
2477 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2478 if d == 15 then // Can only occur for ARM encoding
2479 ALUWritePC(result); // setflags is always FALSE here
2480 else
2481 R[d] = result;
2482 if setflags then
2483 APSR.N = result<31>;
2484 APSR.Z = IsZeroBit(result);
2485 APSR.C = carry;
2486 // APSR.V unchanged
2487#endif
2488
2489 return EmulateShiftImm(encoding, SRType_LSL);
2490}
2491
2492// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2493// shifting in zeros, and writes the result to the destination register. The variable number
2494// of bits is read from the bottom byte of a register. It can optionally update the condition
2495// flags based on the result.
2496bool
2497EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2498{
2499#if 0
2500 // ARM pseudo code...
2501 if ConditionPassed() then
2502 EncodingSpecificOperations();
2503 shift_n = UInt(R[m]<7:0>);
2504 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2505 R[d] = result;
2506 if setflags then
2507 APSR.N = result<31>;
2508 APSR.Z = IsZeroBit(result);
2509 APSR.C = carry;
2510 // APSR.V unchanged
2511#endif
2512
2513 return EmulateShiftReg(encoding, SRType_LSL);
2514}
2515
2516// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2517// shifting in zeros, and writes the result to the destination register. It can optionally
2518// update the condition flags based on the result.
2519bool
2520EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2521{
2522#if 0
2523 // ARM pseudo code...
2524 if ConditionPassed() then
2525 EncodingSpecificOperations();
2526 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2527 if d == 15 then // Can only occur for ARM encoding
2528 ALUWritePC(result); // setflags is always FALSE here
2529 else
2530 R[d] = result;
2531 if setflags then
2532 APSR.N = result<31>;
2533 APSR.Z = IsZeroBit(result);
2534 APSR.C = carry;
2535 // APSR.V unchanged
2536#endif
2537
2538 return EmulateShiftImm(encoding, SRType_LSR);
2539}
2540
2541// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2542// shifting in zeros, and writes the result to the destination register. The variable number
2543// of bits is read from the bottom byte of a register. It can optionally update the condition
2544// flags based on the result.
2545bool
2546EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2547{
2548#if 0
2549 // ARM pseudo code...
2550 if ConditionPassed() then
2551 EncodingSpecificOperations();
2552 shift_n = UInt(R[m]<7:0>);
2553 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2554 R[d] = result;
2555 if setflags then
2556 APSR.N = result<31>;
2557 APSR.Z = IsZeroBit(result);
2558 APSR.C = carry;
2559 // APSR.V unchanged
2560#endif
2561
2562 return EmulateShiftReg(encoding, SRType_LSR);
2563}
2564
Johnny Cheneeab4852011-02-16 22:14:44 +00002565// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2566// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2567// It can optionally update the condition flags based on the result.
2568bool
2569EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2570{
2571#if 0
2572 // ARM pseudo code...
2573 if ConditionPassed() then
2574 EncodingSpecificOperations();
2575 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2576 if d == 15 then // Can only occur for ARM encoding
2577 ALUWritePC(result); // setflags is always FALSE here
2578 else
2579 R[d] = result;
2580 if setflags then
2581 APSR.N = result<31>;
2582 APSR.Z = IsZeroBit(result);
2583 APSR.C = carry;
2584 // APSR.V unchanged
2585#endif
2586
2587 return EmulateShiftImm(encoding, SRType_ROR);
2588}
2589
2590// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2591// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2592// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2593// flags based on the result.
2594bool
2595EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2596{
2597#if 0
2598 // ARM pseudo code...
2599 if ConditionPassed() then
2600 EncodingSpecificOperations();
2601 shift_n = UInt(R[m]<7:0>);
2602 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2603 R[d] = result;
2604 if setflags then
2605 APSR.N = result<31>;
2606 APSR.Z = IsZeroBit(result);
2607 APSR.C = carry;
2608 // APSR.V unchanged
2609#endif
2610
2611 return EmulateShiftReg(encoding, SRType_ROR);
2612}
2613
2614// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2615// with the carry flag shifted into bit [31].
2616//
2617// RRX can optionally update the condition flags based on the result.
2618// In that case, bit [0] is shifted into the carry flag.
2619bool
2620EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2621{
2622#if 0
2623 // ARM pseudo code...
2624 if ConditionPassed() then
2625 EncodingSpecificOperations();
2626 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2627 if d == 15 then // Can only occur for ARM encoding
2628 ALUWritePC(result); // setflags is always FALSE here
2629 else
2630 R[d] = result;
2631 if setflags then
2632 APSR.N = result<31>;
2633 APSR.Z = IsZeroBit(result);
2634 APSR.C = carry;
2635 // APSR.V unchanged
2636#endif
2637
2638 return EmulateShiftImm(encoding, SRType_RRX);
2639}
2640
Johnny Chen41a0a152011-02-16 01:27:54 +00002641bool
2642EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2643{
2644 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2645
Johnny Chen82f16aa2011-02-15 20:10:55 +00002646 bool success = false;
2647 const uint32_t opcode = OpcodeAsUnsigned (&success);
2648 if (!success)
2649 return false;
2650
2651 if (ConditionPassed())
2652 {
Johnny Chene7f89532011-02-15 23:22:46 +00002653 uint32_t Rd; // the destination register
2654 uint32_t Rm; // the first operand register
2655 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002656 uint32_t carry; // the carry bit after the shift operation
2657 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002658
2659 // Special case handling!
2660 // A8.6.139 ROR (immediate) -- Encoding T1
2661 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2662 {
2663 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2664 // have the same decoding of bit fields as the other Thumb2 shift operations.
2665 encoding = eEncodingT2;
2666 }
2667
Johnny Chen82f16aa2011-02-15 20:10:55 +00002668 switch (encoding) {
2669 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002670 // Due to the above special case handling!
2671 assert(shift_type != SRType_ROR);
2672
Johnny Chen82f16aa2011-02-15 20:10:55 +00002673 Rd = Bits32(opcode, 2, 0);
2674 Rm = Bits32(opcode, 5, 3);
2675 setflags = !InITBlock();
2676 imm5 = Bits32(opcode, 10, 6);
2677 break;
2678 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002679 // A8.6.141 RRX
2680 assert(shift_type != SRType_RRX);
2681
Johnny Chen82f16aa2011-02-15 20:10:55 +00002682 Rd = Bits32(opcode, 11, 8);
2683 Rm = Bits32(opcode, 3, 0);
2684 setflags = BitIsSet(opcode, 20);
2685 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2686 if (BadReg(Rd) || BadReg(Rm))
2687 return false;
2688 break;
2689 case eEncodingA1:
2690 Rd = Bits32(opcode, 15, 12);
2691 Rm = Bits32(opcode, 3, 0);
2692 setflags = BitIsSet(opcode, 20);
2693 imm5 = Bits32(opcode, 11, 7);
2694 break;
2695 default:
2696 return false;
2697 }
2698
Johnny Cheneeab4852011-02-16 22:14:44 +00002699 // A8.6.139 ROR (immediate)
2700 if (shift_type == SRType_ROR && imm5 == 0)
2701 shift_type = SRType_RRX;
2702
Johnny Chen82f16aa2011-02-15 20:10:55 +00002703 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002704 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002705 if (!success)
2706 return false;
2707
Johnny Cheneeab4852011-02-16 22:14:44 +00002708 // Decode the shift amount if not RRX.
2709 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002710
Johnny Chene97c0d52011-02-18 19:32:20 +00002711 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002712
2713 // The context specifies that an immediate is to be moved into Rd.
2714 EmulateInstruction::Context context;
2715 context.type = EmulateInstruction::eContextImmediate;
2716 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002717
Johnny Chen10530c22011-02-17 22:37:12 +00002718 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002719 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002720 }
2721 return true;
2722}
2723
Johnny Chene7f89532011-02-15 23:22:46 +00002724bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002725EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002726{
Johnny Chen41a0a152011-02-16 01:27:54 +00002727 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002728
2729 bool success = false;
2730 const uint32_t opcode = OpcodeAsUnsigned (&success);
2731 if (!success)
2732 return false;
2733
2734 if (ConditionPassed())
2735 {
2736 uint32_t Rd; // the destination register
2737 uint32_t Rn; // the first operand register
2738 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2739 uint32_t carry; // the carry bit after the shift operation
2740 bool setflags;
2741 switch (encoding) {
2742 case eEncodingT1:
2743 Rd = Bits32(opcode, 2, 0);
2744 Rn = Rd;
2745 Rm = Bits32(opcode, 5, 3);
2746 setflags = !InITBlock();
2747 break;
2748 case eEncodingT2:
2749 Rd = Bits32(opcode, 11, 8);
2750 Rn = Bits32(opcode, 19, 16);
2751 Rm = Bits32(opcode, 3, 0);
2752 setflags = BitIsSet(opcode, 20);
2753 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2754 return false;
2755 break;
2756 case eEncodingA1:
2757 Rd = Bits32(opcode, 15, 12);
2758 Rn = Bits32(opcode, 3, 0);
2759 Rm = Bits32(opcode, 11, 8);
2760 setflags = BitIsSet(opcode, 20);
2761 if (Rd == 15 || Rn == 15 || Rm == 15)
2762 return false;
2763 break;
2764 default:
2765 return false;
2766 }
2767
2768 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002769 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002770 if (!success)
2771 return false;
2772 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002773 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002774 if (!success)
2775 return false;
2776
2777 // Get the shift amount.
2778 uint32_t amt = Bits32(val, 7, 0);
2779
Johnny Chene97c0d52011-02-18 19:32:20 +00002780 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002781
2782 // The context specifies that an immediate is to be moved into Rd.
2783 EmulateInstruction::Context context;
2784 context.type = EmulateInstruction::eContextImmediate;
2785 context.SetNoArgs ();
2786
Johnny Chen10530c22011-02-17 22:37:12 +00002787 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002788 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002789 }
2790 return true;
2791}
2792
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002793// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002794// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002795// can be written back to the base register.
2796bool
2797EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2798{
2799#if 0
2800 // ARM pseudo code...
2801 if ConditionPassed()
2802 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2803 address = R[n];
2804
2805 for i = 0 to 14
2806 if registers<i> == '1' then
2807 R[i] = MemA[address, 4]; address = address + 4;
2808 if registers<15> == '1' then
2809 LoadWritePC (MemA[address, 4]);
2810
2811 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2812 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2813
2814#endif
2815
2816 bool success = false;
2817 const uint32_t opcode = OpcodeAsUnsigned (&success);
2818 if (!success)
2819 return false;
2820
2821 if (ConditionPassed())
2822 {
2823 uint32_t n;
2824 uint32_t registers = 0;
2825 bool wback;
2826 const uint32_t addr_byte_size = GetAddressByteSize();
2827 switch (encoding)
2828 {
2829 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002830 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002831 n = Bits32 (opcode, 10, 8);
2832 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002833 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002834 wback = BitIsClear (registers, n);
2835 // if BitCount(registers) < 1 then UNPREDICTABLE;
2836 if (BitCount(registers) < 1)
2837 return false;
2838 break;
2839 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002840 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2841 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002842 n = Bits32 (opcode, 19, 16);
2843 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002844 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002845 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002846
2847 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002848 if ((n == 15)
2849 || (BitCount (registers) < 2)
2850 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2851 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002852
2853 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002854 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002855 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002856
2857 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002858 if (wback
2859 && BitIsSet (registers, n))
2860 return false;
2861 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002862
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002863 case eEncodingA1:
2864 n = Bits32 (opcode, 19, 16);
2865 registers = Bits32 (opcode, 15, 0);
2866 wback = BitIsSet (opcode, 21);
2867 if ((n == 15)
2868 || (BitCount (registers) < 1))
2869 return false;
2870 break;
2871 default:
2872 return false;
2873 }
2874
2875 int32_t offset = 0;
2876 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2877 if (!success)
2878 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002879
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002880 EmulateInstruction::Context context;
2881 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2882 Register dwarf_reg;
2883 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2884 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002885
2886 for (int i = 0; i < 14; ++i)
2887 {
2888 if (BitIsSet (registers, i))
2889 {
Caroline Tice85aab332011-02-08 23:56:10 +00002890 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002891 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002892 if (wback && (n == 13)) // Pop Instruction
2893 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2894
2895 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002896 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002897 if (!success)
2898 return false;
2899
2900 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2901 return false;
2902
2903 offset += addr_byte_size;
2904 }
2905 }
2906
2907 if (BitIsSet (registers, 15))
2908 {
2909 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002910 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002911 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002912 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002913 if (!success)
2914 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002915 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002916 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002917 return false;
2918 }
2919
2920 if (wback && BitIsClear (registers, n))
2921 {
Caroline Ticefa172202011-02-11 22:49:54 +00002922 // R[n] = R[n] + 4 * BitCount (registers)
2923 int32_t offset = addr_byte_size * BitCount (registers);
2924 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002925 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002926
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002927 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2928 return false;
2929 }
2930 if (wback && BitIsSet (registers, n))
2931 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002932 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002933 }
2934 return true;
2935}
Caroline Tice713c2662011-02-11 17:59:55 +00002936
2937// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2938// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2939// can optionally be written back tot he base registers.
2940bool
2941EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2942{
2943#if 0
2944 // ARM pseudo code...
2945 if ConditionPassed() then
2946 EncodingSpecificOperations();
2947 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002948
Caroline Tice713c2662011-02-11 17:59:55 +00002949 for i = 0 to 14
2950 if registers<i> == ’1’ then
2951 R[i] = MemA[address,4]; address = address + 4;
2952
2953 if registers<15> == ’1’ then
2954 LoadWritePC(MemA[address,4]);
2955
2956 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2957 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2958#endif
2959
2960 bool success = false;
2961 const uint32_t opcode = OpcodeAsUnsigned (&success);
2962 if (!success)
2963 return false;
2964
2965 if (ConditionPassed())
2966 {
2967 uint32_t n;
2968 uint32_t registers = 0;
2969 bool wback;
2970 const uint32_t addr_byte_size = GetAddressByteSize();
2971
2972 // EncodingSpecificOperations();
2973 switch (encoding)
2974 {
2975 case eEncodingA1:
2976 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2977 n = Bits32 (opcode, 19, 16);
2978 registers = Bits32 (opcode, 15, 0);
2979 wback = BitIsSet (opcode, 21);
2980
2981 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2982 if ((n == 15) || (BitCount (registers) < 1))
2983 return false;
2984
2985 break;
2986
2987 default:
2988 return false;
2989 }
2990 // address = R[n] - 4*BitCount(registers) + 4;
2991
2992 int32_t offset = 0;
2993 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2994
2995 if (!success)
2996 return false;
2997
2998 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2999
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003000 EmulateInstruction::Context context;
3001 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3002 Register dwarf_reg;
3003 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3004 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003005
3006 // for i = 0 to 14
3007 for (int i = 0; i < 14; ++i)
3008 {
3009 // if registers<i> == ’1’ then
3010 if (BitIsSet (registers, i))
3011 {
3012 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003013 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003014 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003015 if (!success)
3016 return false;
3017 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3018 return false;
3019 offset += addr_byte_size;
3020 }
3021 }
3022
3023 // if registers<15> == ’1’ then
3024 // LoadWritePC(MemA[address,4]);
3025 if (BitIsSet (registers, 15))
3026 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003027 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003028 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003029 if (!success)
3030 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003031 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003032 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003033 return false;
3034 }
3035
3036 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3037 if (wback && BitIsClear (registers, n))
3038 {
Caroline Tice713c2662011-02-11 17:59:55 +00003039 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3040 if (!success)
3041 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003042
3043 offset = (addr_byte_size * BitCount (registers)) * -1;
3044 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003045 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003046 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003047 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3048 return false;
3049 }
3050
3051 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3052 if (wback && BitIsSet (registers, n))
3053 return WriteBits32Unknown (n);
3054 }
3055 return true;
3056}
3057
3058// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3059// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3060// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003061bool
3062EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3063{
3064#if 0
3065 // ARM pseudo code...
3066 if ConditionPassed() then
3067 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3068 address = R[n] - 4*BitCount(registers);
3069
3070 for i = 0 to 14
3071 if registers<i> == ’1’ then
3072 R[i] = MemA[address,4]; address = address + 4;
3073 if registers<15> == ’1’ then
3074 LoadWritePC(MemA[address,4]);
3075
3076 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3077 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3078#endif
3079
3080 bool success = false;
3081 const uint32_t opcode = OpcodeAsUnsigned (&success);
3082 if (!success)
3083 return false;
3084
3085 if (ConditionPassed())
3086 {
3087 uint32_t n;
3088 uint32_t registers = 0;
3089 bool wback;
3090 const uint32_t addr_byte_size = GetAddressByteSize();
3091 switch (encoding)
3092 {
3093 case eEncodingT1:
3094 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3095 n = Bits32 (opcode, 19, 16);
3096 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003097 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003098 wback = BitIsSet (opcode, 21);
3099
3100 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3101 if ((n == 15)
3102 || (BitCount (registers) < 2)
3103 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3104 return false;
3105
3106 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003107 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003108 return false;
3109
3110 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3111 if (wback && BitIsSet (registers, n))
3112 return false;
3113
3114 break;
3115
3116 case eEncodingA1:
3117 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3118 n = Bits32 (opcode, 19, 16);
3119 registers = Bits32 (opcode, 15, 0);
3120 wback = BitIsSet (opcode, 21);
3121
3122 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3123 if ((n == 15) || (BitCount (registers) < 1))
3124 return false;
3125
3126 break;
3127
3128 default:
3129 return false;
3130 }
3131
Caroline Tice713c2662011-02-11 17:59:55 +00003132 // address = R[n] - 4*BitCount(registers);
3133
Caroline Tice0b29e242011-02-08 23:16:02 +00003134 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003135 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3136
3137 if (!success)
3138 return false;
3139
3140 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003141 EmulateInstruction::Context context;
3142 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3143 Register dwarf_reg;
3144 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3145 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003146
3147 for (int i = 0; i < 14; ++i)
3148 {
3149 if (BitIsSet (registers, i))
3150 {
3151 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003152 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003153 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003154 if (!success)
3155 return false;
3156
3157 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3158 return false;
3159
3160 offset += addr_byte_size;
3161 }
3162 }
3163
3164 // if registers<15> == ’1’ then
3165 // LoadWritePC(MemA[address,4]);
3166 if (BitIsSet (registers, 15))
3167 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003168 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003169 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003170 if (!success)
3171 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003172 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003173 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003174 return false;
3175 }
3176
3177 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3178 if (wback && BitIsClear (registers, n))
3179 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003180 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3181 if (!success)
3182 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003183
3184 offset = (addr_byte_size * BitCount (registers)) * -1;
3185 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003186 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003187 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3189 return false;
3190 }
3191
3192 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3193 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003194 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003195 }
3196 return true;
3197}
Caroline Tice85aab332011-02-08 23:56:10 +00003198
Caroline Tice713c2662011-02-11 17:59:55 +00003199// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3200// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3201// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003202bool
3203EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3204{
3205#if 0
3206 if ConditionPassed() then
3207 EncodingSpecificOperations();
3208 address = R[n] + 4;
3209
3210 for i = 0 to 14
3211 if registers<i> == ’1’ then
3212 R[i] = MemA[address,4]; address = address + 4;
3213 if registers<15> == ’1’ then
3214 LoadWritePC(MemA[address,4]);
3215
3216 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3217 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3218#endif
3219
3220 bool success = false;
3221 const uint32_t opcode = OpcodeAsUnsigned (&success);
3222 if (!success)
3223 return false;
3224
3225 if (ConditionPassed())
3226 {
3227 uint32_t n;
3228 uint32_t registers = 0;
3229 bool wback;
3230 const uint32_t addr_byte_size = GetAddressByteSize();
3231 switch (encoding)
3232 {
3233 case eEncodingA1:
3234 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3235 n = Bits32 (opcode, 19, 16);
3236 registers = Bits32 (opcode, 15, 0);
3237 wback = BitIsSet (opcode, 21);
3238
3239 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3240 if ((n == 15) || (BitCount (registers) < 1))
3241 return false;
3242
3243 break;
3244 default:
3245 return false;
3246 }
3247 // address = R[n] + 4;
3248
3249 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003250 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3251
3252 if (!success)
3253 return false;
3254
3255 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003256
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003257 EmulateInstruction::Context context;
3258 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3259 Register dwarf_reg;
3260 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3261 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003262
3263 for (int i = 0; i < 14; ++i)
3264 {
3265 if (BitIsSet (registers, i))
3266 {
3267 // R[i] = MemA[address,4]; address = address + 4;
3268
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003269 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003270 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003271 if (!success)
3272 return false;
3273
3274 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3275 return false;
3276
3277 offset += addr_byte_size;
3278 }
3279 }
3280
3281 // if registers<15> == ’1’ then
3282 // LoadWritePC(MemA[address,4]);
3283 if (BitIsSet (registers, 15))
3284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003285 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003286 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003287 if (!success)
3288 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003289 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003290 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003291 return false;
3292 }
3293
3294 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3295 if (wback && BitIsClear (registers, n))
3296 {
Caroline Tice85aab332011-02-08 23:56:10 +00003297 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3298 if (!success)
3299 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003300
3301 offset = addr_byte_size * BitCount (registers);
3302 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003303 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003304 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003305 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3306 return false;
3307 }
3308
3309 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3310 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003311 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003312 }
3313 return true;
3314}
Caroline Tice0b29e242011-02-08 23:16:02 +00003315
Johnny Chenef21b592011-02-10 01:52:38 +00003316// Load Register (immediate) calculates an address from a base register value and
3317// an immediate offset, loads a word from memory, and writes to a register.
3318// LDR (immediate, Thumb)
3319bool
3320EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3321{
3322#if 0
3323 // ARM pseudo code...
3324 if (ConditionPassed())
3325 {
3326 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3327 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3328 address = if index then offset_addr else R[n];
3329 data = MemU[address,4];
3330 if wback then R[n] = offset_addr;
3331 if t == 15 then
3332 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3333 elsif UnalignedSupport() || address<1:0> = '00' then
3334 R[t] = data;
3335 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3336 }
3337#endif
3338
3339 bool success = false;
3340 const uint32_t opcode = OpcodeAsUnsigned (&success);
3341 if (!success)
3342 return false;
3343
3344 if (ConditionPassed())
3345 {
3346 uint32_t Rt; // the destination register
3347 uint32_t Rn; // the base register
3348 uint32_t imm32; // the immediate offset used to form the address
3349 addr_t offset_addr; // the offset address
3350 addr_t address; // the calculated address
3351 uint32_t data; // the literal data value from memory load
3352 bool add, index, wback;
3353 switch (encoding) {
3354 case eEncodingT1:
3355 Rt = Bits32(opcode, 5, 3);
3356 Rn = Bits32(opcode, 2, 0);
3357 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3358 // index = TRUE; add = TRUE; wback = FALSE
3359 add = true;
3360 index = true;
3361 wback = false;
3362 break;
3363 default:
3364 return false;
3365 }
3366 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3367 if (!success)
3368 return false;
3369 if (add)
3370 offset_addr = base + imm32;
3371 else
3372 offset_addr = base - imm32;
3373
3374 address = (index ? offset_addr : base);
3375
3376 if (wback)
3377 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003378 EmulateInstruction::Context ctx;
3379 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3380 Register dwarf_reg;
3381 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3382 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3383
Johnny Chenef21b592011-02-10 01:52:38 +00003384 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3385 return false;
3386 }
3387
3388 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003389 EmulateInstruction::Context context;
3390 context.type = EmulateInstruction::eContextImmediate;
3391 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003392
3393 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003394 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003395 if (!success)
3396 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003397
3398 if (Rt == 15)
3399 {
3400 if (Bits32(address, 1, 0) == 0)
3401 {
Johnny Chen668b4512011-02-15 21:08:58 +00003402 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003403 return false;
3404 }
3405 else
3406 return false;
3407 }
3408 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3409 {
3410 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3411 return false;
3412 }
3413 else
3414 return false;
3415 }
3416 return true;
3417}
3418
Caroline Ticeaf556562011-02-15 18:42:15 +00003419// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3420// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3421// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003422bool
3423EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3424{
3425#if 0
3426 if ConditionPassed() then
3427 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3428 address = R[n];
3429
3430 for i = 0 to 14
3431 if registers<i> == ’1’ then
3432 if i == n && wback && i != LowestSetBit(registers) then
3433 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3434 else
3435 MemA[address,4] = R[i];
3436 address = address + 4;
3437
3438 if registers<15> == ’1’ then // Only possible for encoding A1
3439 MemA[address,4] = PCStoreValue();
3440 if wback then R[n] = R[n] + 4*BitCount(registers);
3441#endif
3442
3443 bool success = false;
3444 const uint32_t opcode = OpcodeAsUnsigned (&success);
3445 if (!success)
3446 return false;
3447
3448 if (ConditionPassed ())
3449 {
3450 uint32_t n;
3451 uint32_t registers = 0;
3452 bool wback;
3453 const uint32_t addr_byte_size = GetAddressByteSize();
3454
3455 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3456 switch (encoding)
3457 {
3458 case eEncodingT1:
3459 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3460 n = Bits32 (opcode, 10, 8);
3461 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003462 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003463 wback = true;
3464
3465 // if BitCount(registers) < 1 then UNPREDICTABLE;
3466 if (BitCount (registers) < 1)
3467 return false;
3468
3469 break;
3470
3471 case eEncodingT2:
3472 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3473 n = Bits32 (opcode, 19, 16);
3474 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003475 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003476 wback = BitIsSet (opcode, 21);
3477
3478 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3479 if ((n == 15) || (BitCount (registers) < 2))
3480 return false;
3481
3482 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3483 if (wback && BitIsSet (registers, n))
3484 return false;
3485
3486 break;
3487
3488 case eEncodingA1:
3489 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3490 n = Bits32 (opcode, 19, 16);
3491 registers = Bits32 (opcode, 15, 0);
3492 wback = BitIsSet (opcode, 21);
3493
3494 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3495 if ((n == 15) || (BitCount (registers) < 1))
3496 return false;
3497
3498 break;
3499
3500 default:
3501 return false;
3502 }
3503
3504 // address = R[n];
3505 int32_t offset = 0;
3506 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3507 if (!success)
3508 return false;
3509
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003510 EmulateInstruction::Context context;
3511 context.type = EmulateInstruction::eContextRegisterStore;
3512 Register base_reg;
3513 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003514
3515 // for i = 0 to 14
3516 for (int i = 0; i < 14; ++i)
3517 {
3518 int lowest_set_bit = 14;
3519 // if registers<i> == ’1’ then
3520 if (BitIsSet (registers, i))
3521 {
3522 if (i < lowest_set_bit)
3523 lowest_set_bit = i;
3524 // if i == n && wback && i != LowestSetBit(registers) then
3525 if ((i == n) && wback && (i != lowest_set_bit))
3526 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3527 WriteBits32UnknownToMemory (address + offset);
3528 else
3529 {
3530 // MemA[address,4] = R[i];
3531 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3532 if (!success)
3533 return false;
3534
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003535 Register data_reg;
3536 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3537 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003538 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003539 return false;
3540 }
3541
3542 // address = address + 4;
3543 offset += addr_byte_size;
3544 }
3545 }
3546
3547 // if registers<15> == ’1’ then // Only possible for encoding A1
3548 // MemA[address,4] = PCStoreValue();
3549 if (BitIsSet (registers, 15))
3550 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003551 Register pc_reg;
3552 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3553 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003554 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3555 if (!success)
3556 return false;
3557
Caroline Ticecc96eb52011-02-17 19:20:40 +00003558 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003559 return false;
3560 }
3561
3562 // if wback then R[n] = R[n] + 4*BitCount(registers);
3563 if (wback)
3564 {
3565 offset = addr_byte_size * BitCount (registers);
3566 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003567 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003568 addr_t data = address + offset;
3569 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3570 return false;
3571 }
3572 }
3573 return true;
3574}
3575
Caroline Ticeaf556562011-02-15 18:42:15 +00003576// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3577// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3578// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003579bool
3580EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3581{
3582#if 0
3583 if ConditionPassed() then
3584 EncodingSpecificOperations();
3585 address = R[n] - 4*BitCount(registers) + 4;
3586
3587 for i = 0 to 14
3588 if registers<i> == ’1’ then
3589 if i == n && wback && i != LowestSetBit(registers) then
3590 MemA[address,4] = bits(32) UNKNOWN;
3591 else
3592 MemA[address,4] = R[i];
3593 address = address + 4;
3594
3595 if registers<15> == ’1’ then
3596 MemA[address,4] = PCStoreValue();
3597
3598 if wback then R[n] = R[n] - 4*BitCount(registers);
3599#endif
3600
3601 bool success = false;
3602 const uint32_t opcode = OpcodeAsUnsigned (&success);
3603 if (!success)
3604 return false;
3605
3606 if (ConditionPassed ())
3607 {
3608 uint32_t n;
3609 uint32_t registers = 0;
3610 bool wback;
3611 const uint32_t addr_byte_size = GetAddressByteSize();
3612
3613 // EncodingSpecificOperations();
3614 switch (encoding)
3615 {
3616 case eEncodingA1:
3617 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3618 n = Bits32 (opcode, 19, 16);
3619 registers = Bits32 (opcode, 15, 0);
3620 wback = BitIsSet (opcode, 21);
3621
3622 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3623 if ((n == 15) || (BitCount (registers) < 1))
3624 return false;
3625 break;
3626 default:
3627 return false;
3628 }
3629
3630 // address = R[n] - 4*BitCount(registers) + 4;
3631 int32_t offset = 0;
3632 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3633 if (!success)
3634 return false;
3635
3636 address = address - (addr_byte_size * BitCount (registers)) + 4;
3637
3638 EmulateInstruction::Context context;
3639 context.type = EmulateInstruction::eContextRegisterStore;
3640 Register base_reg;
3641 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3642
3643 // for i = 0 to 14
3644 for (int i = 0; i < 14; ++i)
3645 {
3646 int lowest_bit_set = 14;
3647 // if registers<i> == ’1’ then
3648 if (BitIsSet (registers, i))
3649 {
3650 if (i < lowest_bit_set)
3651 lowest_bit_set = i;
3652 //if i == n && wback && i != LowestSetBit(registers) then
3653 if ((i == n) && wback && (i != lowest_bit_set))
3654 // MemA[address,4] = bits(32) UNKNOWN;
3655 WriteBits32UnknownToMemory (address + offset);
3656 else
3657 {
3658 // MemA[address,4] = R[i];
3659 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3660 if (!success)
3661 return false;
3662
3663 Register data_reg;
3664 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3665 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003666 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003667 return false;
3668 }
3669
3670 // address = address + 4;
3671 offset += addr_byte_size;
3672 }
3673 }
3674
3675 // if registers<15> == ’1’ then
3676 // MemA[address,4] = PCStoreValue();
3677 if (BitIsSet (registers, 15))
3678 {
3679 Register pc_reg;
3680 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3681 context.SetRegisterPlusOffset (pc_reg, 8);
3682 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3683 if (!success)
3684 return false;
3685
Caroline Ticecc96eb52011-02-17 19:20:40 +00003686 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003687 return false;
3688 }
3689
3690 // if wback then R[n] = R[n] - 4*BitCount(registers);
3691 if (wback)
3692 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003693 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003694 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3695 context.SetImmediateSigned (offset);
3696 addr_t data = address + offset;
3697 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3698 return false;
3699 }
3700 }
3701 return true;
3702}
3703
Caroline Ticeaf556562011-02-15 18:42:15 +00003704// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3705// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3706// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003707bool
3708EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3709{
3710#if 0
3711 if ConditionPassed() then
3712 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3713 address = R[n] - 4*BitCount(registers);
3714
3715 for i = 0 to 14
3716 if registers<i> == ’1’ then
3717 if i == n && wback && i != LowestSetBit(registers) then
3718 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3719 else
3720 MemA[address,4] = R[i];
3721 address = address + 4;
3722
3723 if registers<15> == ’1’ then // Only possible for encoding A1
3724 MemA[address,4] = PCStoreValue();
3725
3726 if wback then R[n] = R[n] - 4*BitCount(registers);
3727#endif
3728
3729
3730 bool success = false;
3731 const uint32_t opcode = OpcodeAsUnsigned (&success);
3732 if (!success)
3733 return false;
3734
3735 if (ConditionPassed ())
3736 {
3737 uint32_t n;
3738 uint32_t registers = 0;
3739 bool wback;
3740 const uint32_t addr_byte_size = GetAddressByteSize();
3741
3742 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3743 switch (encoding)
3744 {
3745 case eEncodingT1:
3746 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3747 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3748 {
3749 // See PUSH
3750 }
3751 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3752 n = Bits32 (opcode, 19, 16);
3753 registers = Bits32 (opcode, 15, 0);
3754 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3755 wback = BitIsSet (opcode, 21);
3756 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3757 if ((n == 15) || BitCount (registers) < 2)
3758 return false;
3759 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3760 if (wback && BitIsSet (registers, n))
3761 return false;
3762 break;
3763
3764 case eEncodingA1:
3765 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3766 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3767 {
3768 // See Push
3769 }
3770 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3771 n = Bits32 (opcode, 19, 16);
3772 registers = Bits32 (opcode, 15, 0);
3773 wback = BitIsSet (opcode, 21);
3774 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3775 if ((n == 15) || BitCount (registers) < 1)
3776 return false;
3777 break;
3778
3779 default:
3780 return false;
3781 }
3782
3783 // address = R[n] - 4*BitCount(registers);
3784
3785 int32_t offset = 0;
3786 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3787 if (!success)
3788 return false;
3789
3790 address = address - (addr_byte_size * BitCount (registers));
3791
3792 EmulateInstruction::Context context;
3793 context.type = EmulateInstruction::eContextRegisterStore;
3794 Register base_reg;
3795 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3796
3797 // for i = 0 to 14
3798 for (int i = 0; i < 14; ++i)
3799 {
3800 uint32_t lowest_set_bit = 14;
3801 // if registers<i> == ’1’ then
3802 if (BitIsSet (registers, i))
3803 {
3804 if (i < lowest_set_bit)
3805 lowest_set_bit = i;
3806 // if i == n && wback && i != LowestSetBit(registers) then
3807 if ((i == n) && wback && (i != lowest_set_bit))
3808 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3809 WriteBits32UnknownToMemory (address + offset);
3810 else
3811 {
3812 // MemA[address,4] = R[i];
3813 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3814 if (!success)
3815 return false;
3816
3817 Register data_reg;
3818 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3819 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003820 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003821 return false;
3822 }
3823
3824 // address = address + 4;
3825 offset += addr_byte_size;
3826 }
3827 }
3828
3829 // if registers<15> == ’1’ then // Only possible for encoding A1
3830 // MemA[address,4] = PCStoreValue();
3831 if (BitIsSet (registers, 15))
3832 {
3833 Register pc_reg;
3834 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3835 context.SetRegisterPlusOffset (pc_reg, 8);
3836 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3837 if (!success)
3838 return false;
3839
Caroline Ticecc96eb52011-02-17 19:20:40 +00003840 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003841 return false;
3842 }
3843
3844 // if wback then R[n] = R[n] - 4*BitCount(registers);
3845 if (wback)
3846 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003847 offset = (addr_byte_size * BitCount (registers)) * -1;
3848 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3849 context.SetImmediateSigned (offset);
3850 addr_t data = address + offset;
3851 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3852 return false;
3853 }
3854 }
3855 return true;
3856}
3857
3858// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3859// from a base register. The consecutive memory locations start just above this address, and the address of the last
3860// of those locations can optionally be written back to the base register.
3861bool
3862EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3863{
3864#if 0
3865 if ConditionPassed() then
3866 EncodingSpecificOperations();
3867 address = R[n] + 4;
3868
3869 for i = 0 to 14
3870 if registers<i> == ’1’ then
3871 if i == n && wback && i != LowestSetBit(registers) then
3872 MemA[address,4] = bits(32) UNKNOWN;
3873 else
3874 MemA[address,4] = R[i];
3875 address = address + 4;
3876
3877 if registers<15> == ’1’ then
3878 MemA[address,4] = PCStoreValue();
3879
3880 if wback then R[n] = R[n] + 4*BitCount(registers);
3881#endif
3882
3883 bool success = false;
3884 const uint32_t opcode = OpcodeAsUnsigned (&success);
3885 if (!success)
3886 return false;
3887
3888 if (ConditionPassed())
3889 {
3890 uint32_t n;
3891 uint32_t registers = 0;
3892 bool wback;
3893 const uint32_t addr_byte_size = GetAddressByteSize();
3894
3895 // EncodingSpecificOperations();
3896 switch (encoding)
3897 {
3898 case eEncodingA1:
3899 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3900 n = Bits32 (opcode, 19, 16);
3901 registers = Bits32 (opcode, 15, 0);
3902 wback = BitIsSet (opcode, 21);
3903
3904 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3905 if ((n == 15) && (BitCount (registers) < 1))
3906 return false;
3907 break;
3908 default:
3909 return false;
3910 }
3911 // address = R[n] + 4;
3912
3913 int32_t offset = 0;
3914 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3915 if (!success)
3916 return false;
3917
3918 address = address + addr_byte_size;
3919
3920 EmulateInstruction::Context context;
3921 context.type = EmulateInstruction::eContextRegisterStore;
3922 Register base_reg;
3923 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3924
3925 uint32_t lowest_set_bit = 14;
3926 // for i = 0 to 14
3927 for (int i = 0; i < 14; ++i)
3928 {
3929 // if registers<i> == ’1’ then
3930 if (BitIsSet (registers, i))
3931 {
3932 if (i < lowest_set_bit)
3933 lowest_set_bit = i;
3934 // if i == n && wback && i != LowestSetBit(registers) then
3935 if ((i == n) && wback && (i != lowest_set_bit))
3936 // MemA[address,4] = bits(32) UNKNOWN;
3937 WriteBits32UnknownToMemory (address + offset);
3938 // else
3939 else
3940 {
3941 // MemA[address,4] = R[i];
3942 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3943 if (!success)
3944 return false;
3945
3946 Register data_reg;
3947 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3948 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003949 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003950 return false;
3951 }
3952
3953 // address = address + 4;
3954 offset += addr_byte_size;
3955 }
3956 }
3957
3958 // if registers<15> == ’1’ then
3959 // MemA[address,4] = PCStoreValue();
3960 if (BitIsSet (registers, 15))
3961 {
3962 Register pc_reg;
3963 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3964 context.SetRegisterPlusOffset (pc_reg, 8);
3965 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3966 if (!success)
3967 return false;
3968
Caroline Ticecc96eb52011-02-17 19:20:40 +00003969 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003970 return false;
3971 }
3972
3973 // if wback then R[n] = R[n] + 4*BitCount(registers);
3974 if (wback)
3975 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003976 offset = addr_byte_size * BitCount (registers);
3977 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3978 context.SetImmediateSigned (offset);
3979 addr_t data = address + offset;
3980 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3981 return false;
3982 }
3983 }
3984 return true;
3985}
Caroline Tice7fac8572011-02-15 22:53:54 +00003986
3987// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3988// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3989bool
3990EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3991{
3992#if 0
3993 if ConditionPassed() then
3994 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3995 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3996 address = if index then offset_addr else R[n];
3997 if UnalignedSupport() || address<1:0> == ’00’ then
3998 MemU[address,4] = R[t];
3999 else // Can only occur before ARMv7
4000 MemU[address,4] = bits(32) UNKNOWN;
4001 if wback then R[n] = offset_addr;
4002#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004003
Caroline Tice7fac8572011-02-15 22:53:54 +00004004 bool success = false;
4005 const uint32_t opcode = OpcodeAsUnsigned (&success);
4006 if (!success)
4007 return false;
4008
4009 if (ConditionPassed())
4010 {
4011 const uint32_t addr_byte_size = GetAddressByteSize();
4012
4013 uint32_t t;
4014 uint32_t n;
4015 uint32_t imm32;
4016 bool index;
4017 bool add;
4018 bool wback;
4019 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4020 switch (encoding)
4021 {
4022 case eEncodingT1:
4023 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4024 t = Bits32 (opcode, 2, 0);
4025 n = Bits32 (opcode, 5, 3);
4026 imm32 = Bits32 (opcode, 10, 6) << 2;
4027
4028 // index = TRUE; add = TRUE; wback = FALSE;
4029 index = true;
4030 add = false;
4031 wback = false;
4032 break;
4033
4034 case eEncodingT2:
4035 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4036 t = Bits32 (opcode, 10, 8);
4037 n = 13;
4038 imm32 = Bits32 (opcode, 7, 0) << 2;
4039
4040 // index = TRUE; add = TRUE; wback = FALSE;
4041 index = true;
4042 add = true;
4043 wback = false;
4044 break;
4045
4046 case eEncodingT3:
4047 // if Rn == ’1111’ then UNDEFINED;
4048 if (Bits32 (opcode, 19, 16) == 15)
4049 return false;
4050
4051 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4052 t = Bits32 (opcode, 15, 12);
4053 n = Bits32 (opcode, 19, 16);
4054 imm32 = Bits32 (opcode, 11, 0);
4055
4056 // index = TRUE; add = TRUE; wback = FALSE;
4057 index = true;
4058 add = true;
4059 wback = false;
4060
4061 // if t == 15 then UNPREDICTABLE;
4062 if (t == 15)
4063 return false;
4064 break;
4065
4066 case eEncodingT4:
4067 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4068 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4069 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4070 if ((Bits32 (opcode, 19, 16) == 15)
4071 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4072 return false;
4073
4074 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4075 t = Bits32 (opcode, 15, 12);
4076 n = Bits32 (opcode, 19, 16);
4077 imm32 = Bits32 (opcode, 7, 0);
4078
4079 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4080 index = BitIsSet (opcode, 10);
4081 add = BitIsSet (opcode, 9);
4082 wback = BitIsSet (opcode, 8);
4083
4084 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4085 if ((t == 15) || (wback && (n == t)))
4086 return false;
4087 break;
4088
4089 default:
4090 return false;
4091 }
4092
4093 addr_t offset_addr;
4094 addr_t address;
4095
4096 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4097 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4098 if (!success)
4099 return false;
4100
4101 if (add)
4102 offset_addr = base_address + imm32;
4103 else
4104 offset_addr = base_address - imm32;
4105
4106 // address = if index then offset_addr else R[n];
4107 if (index)
4108 address = offset_addr;
4109 else
4110 address = base_address;
4111
4112 EmulateInstruction::Context context;
4113 context.type = eContextRegisterStore;
4114 Register base_reg;
4115 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4116
4117 // if UnalignedSupport() || address<1:0> == ’00’ then
4118 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4119 {
4120 // MemU[address,4] = R[t];
4121 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4122 if (!success)
4123 return false;
4124
4125 Register data_reg;
4126 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4127 int32_t offset = address - base_address;
4128 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004129 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004130 return false;
4131 }
4132 else
4133 {
4134 // MemU[address,4] = bits(32) UNKNOWN;
4135 WriteBits32UnknownToMemory (address);
4136 }
4137
4138 // if wback then R[n] = offset_addr;
4139 if (wback)
4140 {
4141 context.type = eContextRegisterLoad;
4142 context.SetAddress (offset_addr);
4143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4144 return false;
4145 }
4146 }
4147 return true;
4148}
Caroline Ticeaf556562011-02-15 18:42:15 +00004149
Caroline Tice3fd63e92011-02-16 00:33:43 +00004150// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4151// word from a register to memory. The offset register value can optionally be shifted.
4152bool
4153EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4154{
4155#if 0
4156 if ConditionPassed() then
4157 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4158 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4159 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4160 address = if index then offset_addr else R[n];
4161 if t == 15 then // Only possible for encoding A1
4162 data = PCStoreValue();
4163 else
4164 data = R[t];
4165 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4166 MemU[address,4] = data;
4167 else // Can only occur before ARMv7
4168 MemU[address,4] = bits(32) UNKNOWN;
4169 if wback then R[n] = offset_addr;
4170#endif
4171
4172 bool success = false;
4173 const uint32_t opcode = OpcodeAsUnsigned (&success);
4174 if (!success)
4175 return false;
4176
4177 if (ConditionPassed())
4178 {
4179 const uint32_t addr_byte_size = GetAddressByteSize();
4180
4181 uint32_t t;
4182 uint32_t n;
4183 uint32_t m;
4184 ARM_ShifterType shift_t;
4185 uint32_t shift_n;
4186 bool index;
4187 bool add;
4188 bool wback;
4189
4190 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4191 switch (encoding)
4192 {
4193 case eEncodingT1:
4194 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4195 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4196 t = Bits32 (opcode, 2, 0);
4197 n = Bits32 (opcode, 5, 3);
4198 m = Bits32 (opcode, 8, 6);
4199
4200 // index = TRUE; add = TRUE; wback = FALSE;
4201 index = true;
4202 add = true;
4203 wback = false;
4204
4205 // (shift_t, shift_n) = (SRType_LSL, 0);
4206 shift_t = SRType_LSL;
4207 shift_n = 0;
4208 break;
4209
4210 case eEncodingT2:
4211 // if Rn == ’1111’ then UNDEFINED;
4212 if (Bits32 (opcode, 19, 16) == 15)
4213 return false;
4214
4215 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4216 t = Bits32 (opcode, 15, 12);
4217 n = Bits32 (opcode, 19, 16);
4218 m = Bits32 (opcode, 3, 0);
4219
4220 // index = TRUE; add = TRUE; wback = FALSE;
4221 index = true;
4222 add = true;
4223 wback = false;
4224
4225 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4226 shift_t = SRType_LSL;
4227 shift_n = Bits32 (opcode, 5, 4);
4228
4229 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4230 if ((t == 15) || (BadReg (m)))
4231 return false;
4232 break;
4233
4234 case eEncodingA1:
4235 {
4236 // if P == ’0’ && W == ’1’ then SEE STRT;
4237 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4238 t = Bits32 (opcode, 15, 12);
4239 n = Bits32 (opcode, 19, 16);
4240 m = Bits32 (opcode, 3, 0);
4241
4242 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4243 index = BitIsSet (opcode, 24);
4244 add = BitIsSet (opcode, 23);
4245 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4246
4247 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4248 uint32_t typ = Bits32 (opcode, 6, 5);
4249 uint32_t imm5 = Bits32 (opcode, 11, 7);
4250 shift_n = DecodeImmShift(typ, imm5, shift_t);
4251
4252 // if m == 15 then UNPREDICTABLE;
4253 if (m == 15)
4254 return false;
4255
4256 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4257 if (wback && ((n == 15) || (n == t)))
4258 return false;
4259
4260 break;
4261 }
4262 default:
4263 return false;
4264 }
4265
4266 addr_t offset_addr;
4267 addr_t address;
4268 int32_t offset = 0;
4269
4270 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4271 if (!success)
4272 return false;
4273
4274 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4275 if (!success)
4276 return false;
4277
4278 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004279 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004280
4281 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4282 if (add)
4283 offset_addr = base_address + offset;
4284 else
4285 offset_addr = base_address - offset;
4286
4287 // address = if index then offset_addr else R[n];
4288 if (index)
4289 address = offset_addr;
4290 else
4291 address = base_address;
4292
4293 uint32_t data;
4294 // if t == 15 then // Only possible for encoding A1
4295 if (t == 15)
4296 // data = PCStoreValue();
4297 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4298 else
4299 // data = R[t];
4300 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4301
4302 if (!success)
4303 return false;
4304
4305 EmulateInstruction::Context context;
4306 context.type = eContextRegisterStore;
4307
4308 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4309 if (UnalignedSupport ()
4310 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4311 || CurrentInstrSet() == eModeARM)
4312 {
4313 // MemU[address,4] = data;
4314
4315 Register base_reg;
4316 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4317
4318 Register data_reg;
4319 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4320
4321 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004322 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004323 return false;
4324
4325 }
4326 else
4327 // MemU[address,4] = bits(32) UNKNOWN;
4328 WriteBits32UnknownToMemory (address);
4329
4330 // if wback then R[n] = offset_addr;
4331 if (wback)
4332 {
4333 context.type = eContextRegisterLoad;
4334 context.SetAddress (offset_addr);
4335 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4336 return false;
4337 }
4338
4339 }
4340 return true;
4341}
Caroline Tice73a29de2011-02-16 20:22:22 +00004342
4343bool
4344EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4345{
4346#if 0
4347 if ConditionPassed() then
4348 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4349 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4350 address = if index then offset_addr else R[n];
4351 MemU[address,1] = R[t]<7:0>;
4352 if wback then R[n] = offset_addr;
4353#endif
4354
4355
4356 bool success = false;
4357 const uint32_t opcode = OpcodeAsUnsigned (&success);
4358 if (!success)
4359 return false;
4360
4361 if (ConditionPassed ())
4362 {
4363 uint32_t t;
4364 uint32_t n;
4365 uint32_t imm32;
4366 bool index;
4367 bool add;
4368 bool wback;
4369 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4370 switch (encoding)
4371 {
4372 case eEncodingT1:
4373 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4374 t = Bits32 (opcode, 2, 0);
4375 n = Bits32 (opcode, 5, 3);
4376 imm32 = Bits32 (opcode, 10, 6);
4377
4378 // index = TRUE; add = TRUE; wback = FALSE;
4379 index = true;
4380 add = true;
4381 wback = false;
4382 break;
4383
4384 case eEncodingT2:
4385 // if Rn == ’1111’ then UNDEFINED;
4386 if (Bits32 (opcode, 19, 16) == 15)
4387 return false;
4388
4389 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4390 t = Bits32 (opcode, 15, 12);
4391 n = Bits32 (opcode, 19, 16);
4392 imm32 = Bits32 (opcode, 11, 0);
4393
4394 // index = TRUE; add = TRUE; wback = FALSE;
4395 index = true;
4396 add = true;
4397 wback = false;
4398
4399 // if BadReg(t) then UNPREDICTABLE;
4400 if (BadReg (t))
4401 return false;
4402 break;
4403
4404 case eEncodingT3:
4405 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4406 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4407 if (Bits32 (opcode, 19, 16) == 15)
4408 return false;
4409
4410 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4411 t = Bits32 (opcode, 15, 12);
4412 n = Bits32 (opcode, 19, 16);
4413 imm32 = Bits32 (opcode, 7, 0);
4414
4415 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4416 index = BitIsSet (opcode, 10);
4417 add = BitIsSet (opcode, 9);
4418 wback = BitIsSet (opcode, 8);
4419
4420 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4421 if ((BadReg (t)) || (wback && (n == t)))
4422 return false;
4423 break;
4424
4425 default:
4426 return false;
4427 }
4428
4429 addr_t offset_addr;
4430 addr_t address;
4431 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4432 if (!success)
4433 return false;
4434
4435 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4436 if (add)
4437 offset_addr = base_address + imm32;
4438 else
4439 offset_addr = base_address - imm32;
4440
4441 // address = if index then offset_addr else R[n];
4442 if (index)
4443 address = offset_addr;
4444 else
4445 address = base_address;
4446
Caroline Ticecc96eb52011-02-17 19:20:40 +00004447 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004448 Register base_reg;
4449 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4450
4451 Register data_reg;
4452 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4453
4454 EmulateInstruction::Context context;
4455 context.type = eContextRegisterStore;
4456 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4457
4458 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4459 if (!success)
4460 return false;
4461
4462 data = Bits32 (data, 7, 0);
4463
Caroline Ticecc96eb52011-02-17 19:20:40 +00004464 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004465 return false;
4466
4467 // if wback then R[n] = offset_addr;
4468 if (wback)
4469 {
4470 context.type = eContextRegisterLoad;
4471 context.SetAddress (offset_addr);
4472 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4473 return false;
4474 }
4475
4476 }
4477
4478 return true;
4479}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004480
Johnny Chen157b9592011-02-18 21:13:05 +00004481// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4482// and writes the result to the destination register. It can optionally update the condition flags
4483// based on the result.
4484bool
4485EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4486{
4487#if 0
4488 // ARM pseudo code...
4489 if ConditionPassed() then
4490 EncodingSpecificOperations();
4491 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4492 if d == 15 then // Can only occur for ARM encoding
4493 ALUWritePC(result); // setflags is always FALSE here
4494 else
4495 R[d] = result;
4496 if setflags then
4497 APSR.N = result<31>;
4498 APSR.Z = IsZeroBit(result);
4499 APSR.C = carry;
4500 APSR.V = overflow;
4501#endif
4502
4503 bool success = false;
4504 const uint32_t opcode = OpcodeAsUnsigned (&success);
4505 if (!success)
4506 return false;
4507
4508 if (ConditionPassed())
4509 {
4510 uint32_t Rd, Rn;
4511 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4512 bool setflags;
4513 switch (encoding)
4514 {
4515 case eEncodingT1:
4516 Rd = Bits32(opcode, 11, 8);
4517 Rn = Bits32(opcode, 19, 16);
4518 setflags = BitIsSet(opcode, 20);
4519 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4520 if (BadReg(Rd) || BadReg(Rn))
4521 return false;
4522 break;
4523 case eEncodingA1:
4524 Rd = Bits32(opcode, 15, 12);
4525 Rn = Bits32(opcode, 19, 16);
4526 setflags = BitIsSet(opcode, 20);
4527 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4528 // TODO: Emulate SUBS PC, LR and related instructions.
4529 if (Rd == 15 && setflags)
4530 return false;
4531 break;
4532 default:
4533 return false;
4534 }
4535
4536 // Read the first operand.
4537 int32_t val1 = ReadCoreReg(Rn, &success);
4538 if (!success)
4539 return false;
4540
4541 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4542
4543 EmulateInstruction::Context context;
4544 context.type = EmulateInstruction::eContextImmediate;
4545 context.SetNoArgs ();
4546
4547 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4548 return false;
4549 }
4550 return true;
4551}
4552
4553// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4554// register value, and writes the result to the destination register. It can optionally update the
4555// condition flags based on the result.
4556bool
4557EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4558{
4559#if 0
4560 // ARM pseudo code...
4561 if ConditionPassed() then
4562 EncodingSpecificOperations();
4563 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4564 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4565 if d == 15 then // Can only occur for ARM encoding
4566 ALUWritePC(result); // setflags is always FALSE here
4567 else
4568 R[d] = result;
4569 if setflags then
4570 APSR.N = result<31>;
4571 APSR.Z = IsZeroBit(result);
4572 APSR.C = carry;
4573 APSR.V = overflow;
4574#endif
4575
4576 bool success = false;
4577 const uint32_t opcode = OpcodeAsUnsigned (&success);
4578 if (!success)
4579 return false;
4580
4581 if (ConditionPassed())
4582 {
4583 uint32_t Rd, Rn, Rm;
4584 ARM_ShifterType shift_t;
4585 uint32_t shift_n; // the shift applied to the value read from Rm
4586 bool setflags;
4587 switch (encoding)
4588 {
4589 case eEncodingT1:
4590 Rd = Rn = Bits32(opcode, 2, 0);
4591 Rm = Bits32(opcode, 5, 3);
4592 setflags = !InITBlock();
4593 shift_t = SRType_LSL;
4594 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004595 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004596 case eEncodingT2:
4597 Rd = Bits32(opcode, 11, 8);
4598 Rn = Bits32(opcode, 19, 16);
4599 Rm = Bits32(opcode, 3, 0);
4600 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004601 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004602 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4603 return false;
4604 break;
4605 case eEncodingA1:
4606 Rd = Bits32(opcode, 15, 12);
4607 Rn = Bits32(opcode, 19, 16);
4608 Rm = Bits32(opcode, 3, 0);
4609 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004610 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004611 // TODO: Emulate SUBS PC, LR and related instructions.
4612 if (Rd == 15 && setflags)
4613 return false;
4614 break;
4615 default:
4616 return false;
4617 }
4618
4619 // Read the first operand.
4620 int32_t val1 = ReadCoreReg(Rn, &success);
4621 if (!success)
4622 return false;
4623
4624 // Read the second operand.
4625 int32_t val2 = ReadCoreReg(Rm, &success);
4626 if (!success)
4627 return false;
4628
4629 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4630 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4631
4632 EmulateInstruction::Context context;
4633 context.type = EmulateInstruction::eContextImmediate;
4634 context.SetNoArgs ();
4635
4636 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4637 return false;
4638 }
4639 return true;
4640}
4641
Johnny Chene97c0d52011-02-18 19:32:20 +00004642// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4643// to the destination register. It can optionally update the condition flags based on the result.
4644bool
4645EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4646{
4647#if 0
4648 // ARM pseudo code...
4649 if ConditionPassed() then
4650 EncodingSpecificOperations();
4651 result = R[n] AND imm32;
4652 if d == 15 then // Can only occur for ARM encoding
4653 ALUWritePC(result); // setflags is always FALSE here
4654 else
4655 R[d] = result;
4656 if setflags then
4657 APSR.N = result<31>;
4658 APSR.Z = IsZeroBit(result);
4659 APSR.C = carry;
4660 // APSR.V unchanged
4661#endif
4662
4663 bool success = false;
4664 const uint32_t opcode = OpcodeAsUnsigned (&success);
4665 if (!success)
4666 return false;
4667
4668 if (ConditionPassed())
4669 {
4670 uint32_t Rd, Rn;
4671 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4672 bool setflags;
4673 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4674 switch (encoding)
4675 {
4676 case eEncodingT1:
4677 Rd = Bits32(opcode, 11, 8);
4678 Rn = Bits32(opcode, 19, 16);
4679 setflags = BitIsSet(opcode, 20);
4680 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004681 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004682 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004683 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004684 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4685 return false;
4686 break;
4687 case eEncodingA1:
4688 Rd = Bits32(opcode, 15, 12);
4689 Rn = Bits32(opcode, 19, 16);
4690 setflags = BitIsSet(opcode, 20);
4691 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4692 // TODO: Emulate SUBS PC, LR and related instructions.
4693 if (Rd == 15 && setflags)
4694 return false;
4695 break;
4696 default:
4697 return false;
4698 }
4699
Johnny Chene97c0d52011-02-18 19:32:20 +00004700 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004701 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004702 if (!success)
4703 return false;
4704
4705 uint32_t result = val1 & imm32;
4706
4707 EmulateInstruction::Context context;
4708 context.type = EmulateInstruction::eContextImmediate;
4709 context.SetNoArgs ();
4710
4711 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4712 return false;
4713 }
4714 return true;
4715}
4716
4717// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4718// and writes the result to the destination register. It can optionally update the condition flags
4719// based on the result.
4720bool
4721EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4722{
4723#if 0
4724 // ARM pseudo code...
4725 if ConditionPassed() then
4726 EncodingSpecificOperations();
4727 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4728 result = R[n] AND shifted;
4729 if d == 15 then // Can only occur for ARM encoding
4730 ALUWritePC(result); // setflags is always FALSE here
4731 else
4732 R[d] = result;
4733 if setflags then
4734 APSR.N = result<31>;
4735 APSR.Z = IsZeroBit(result);
4736 APSR.C = carry;
4737 // APSR.V unchanged
4738#endif
4739
4740 bool success = false;
4741 const uint32_t opcode = OpcodeAsUnsigned (&success);
4742 if (!success)
4743 return false;
4744
4745 if (ConditionPassed())
4746 {
4747 uint32_t Rd, Rn, Rm;
4748 ARM_ShifterType shift_t;
4749 uint32_t shift_n; // the shift applied to the value read from Rm
4750 bool setflags;
4751 uint32_t carry;
4752 switch (encoding)
4753 {
4754 case eEncodingT1:
4755 Rd = Rn = Bits32(opcode, 2, 0);
4756 Rm = Bits32(opcode, 5, 3);
4757 setflags = !InITBlock();
4758 shift_t = SRType_LSL;
4759 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004760 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004761 case eEncodingT2:
4762 Rd = Bits32(opcode, 11, 8);
4763 Rn = Bits32(opcode, 19, 16);
4764 Rm = Bits32(opcode, 3, 0);
4765 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004766 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004767 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004768 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004769 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004770 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4771 return false;
4772 break;
4773 case eEncodingA1:
4774 Rd = Bits32(opcode, 15, 12);
4775 Rn = Bits32(opcode, 19, 16);
4776 Rm = Bits32(opcode, 3, 0);
4777 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004778 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004779 // TODO: Emulate SUBS PC, LR and related instructions.
4780 if (Rd == 15 && setflags)
4781 return false;
4782 break;
4783 default:
4784 return false;
4785 }
4786
Johnny Chene97c0d52011-02-18 19:32:20 +00004787 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004788 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004789 if (!success)
4790 return false;
4791
4792 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004793 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004794 if (!success)
4795 return false;
4796
4797 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4798 uint32_t result = val1 & shifted;
4799
4800 EmulateInstruction::Context context;
4801 context.type = EmulateInstruction::eContextImmediate;
4802 context.SetNoArgs ();
4803
4804 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4805 return false;
4806 }
4807 return true;
4808}
4809
Caroline Tice4d729c52011-02-18 00:55:53 +00004810// 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 +00004811// 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 +00004812bool
4813EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4814{
4815#if 0
4816 if ConditionPassed() then
4817 EncodingSpecificOperations();
4818 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4819 address = if index then offset_addr else R[n];
4820 data = MemU[address,4];
4821 if wback then R[n] = offset_addr;
4822 if t == 15 then
4823 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4824 elsif UnalignedSupport() || address<1:0> = ’00’ then
4825 R[t] = data;
4826 else // Can only apply before ARMv7
4827 R[t] = ROR(data, 8*UInt(address<1:0>));
4828#endif
4829
4830 bool success = false;
4831 const uint32_t opcode = OpcodeAsUnsigned (&success);
4832 if (!success)
4833 return false;
4834
4835 if (ConditionPassed ())
4836 {
4837 const uint32_t addr_byte_size = GetAddressByteSize();
4838
4839 uint32_t t;
4840 uint32_t n;
4841 uint32_t imm32;
4842 bool index;
4843 bool add;
4844 bool wback;
4845
4846 switch (encoding)
4847 {
4848 case eEncodingA1:
4849 // if Rn == ’1111’ then SEE LDR (literal);
4850 // if P == ’0’ && W == ’1’ then SEE LDRT;
4851 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4852 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4853 t = Bits32 (opcode, 15, 12);
4854 n = Bits32 (opcode, 19, 16);
4855 imm32 = Bits32 (opcode, 11, 0);
4856
4857 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4858 index = BitIsSet (opcode, 24);
4859 add = BitIsSet (opcode, 23);
4860 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4861
4862 // if wback && n == t then UNPREDICTABLE;
4863 if (wback && (n == t))
4864 return false;
4865
4866 break;
4867
4868 default:
4869 return false;
4870 }
4871
4872 addr_t address;
4873 addr_t offset_addr;
4874 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4875 if (!success)
4876 return false;
4877
4878 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4879 if (add)
4880 offset_addr = base_address + imm32;
4881 else
4882 offset_addr = base_address - imm32;
4883
4884 // address = if index then offset_addr else R[n];
4885 if (index)
4886 address = offset_addr;
4887 else
4888 address = base_address;
4889
4890 // data = MemU[address,4];
4891
4892 Register base_reg;
4893 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4894
4895 EmulateInstruction::Context context;
4896 context.type = eContextRegisterLoad;
4897 context.SetRegisterPlusOffset (base_reg, address - base_address);
4898
4899 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4900 if (!success)
4901 return false;
4902
4903 // if wback then R[n] = offset_addr;
4904 if (wback)
4905 {
4906 context.type = eContextAdjustBaseRegister;
4907 context.SetAddress (offset_addr);
4908 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4909 return false;
4910 }
4911
4912 // if t == 15 then
4913 if (t == 15)
4914 {
4915 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4916 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4917 {
4918 // LoadWritePC (data);
4919 context.type = eContextRegisterLoad;
4920 context.SetRegisterPlusOffset (base_reg, address - base_address);
4921 LoadWritePC (context, data);
4922 }
4923 else
4924 return false;
4925 }
4926 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4927 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4928 {
4929 // R[t] = data;
4930 context.type = eContextRegisterLoad;
4931 context.SetRegisterPlusOffset (base_reg, address - base_address);
4932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4933 return false;
4934 }
4935 // else // Can only apply before ARMv7
4936 else
4937 {
4938 // R[t] = ROR(data, 8*UInt(address<1:0>));
4939 data = ROR (data, Bits32 (address, 1, 0));
4940 context.type = eContextRegisterLoad;
4941 context.SetImmediate (data);
4942 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4943 return false;
4944 }
4945
4946 }
4947 return true;
4948}
4949
Caroline Ticefe479112011-02-18 18:52:37 +00004950// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4951// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4952bool
4953EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4954{
4955#if 0
4956 if ConditionPassed() then
4957 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4958 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4959 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4960 address = if index then offset_addr else R[n];
4961 data = MemU[address,4];
4962 if wback then R[n] = offset_addr;
4963 if t == 15 then
4964 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4965 elsif UnalignedSupport() || address<1:0> = ’00’ then
4966 R[t] = data;
4967 else // Can only apply before ARMv7
4968 if CurrentInstrSet() == InstrSet_ARM then
4969 R[t] = ROR(data, 8*UInt(address<1:0>));
4970 else
4971 R[t] = bits(32) UNKNOWN;
4972#endif
4973
4974 bool success = false;
4975 const uint32_t opcode = OpcodeAsUnsigned (&success);
4976 if (!success)
4977 return false;
4978
4979 if (ConditionPassed ())
4980 {
4981 const uint32_t addr_byte_size = GetAddressByteSize();
4982
4983 uint32_t t;
4984 uint32_t n;
4985 uint32_t m;
4986 bool index;
4987 bool add;
4988 bool wback;
4989 ARM_ShifterType shift_t;
4990 uint32_t shift_n;
4991
4992 switch (encoding)
4993 {
4994 case eEncodingT1:
4995 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4996 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4997 t = Bits32 (opcode, 2, 0);
4998 n = Bits32 (opcode, 5, 3);
4999 m = Bits32 (opcode, 8, 6);
5000
5001 // index = TRUE; add = TRUE; wback = FALSE;
5002 index = true;
5003 add = true;
5004 wback = false;
5005
5006 // (shift_t, shift_n) = (SRType_LSL, 0);
5007 shift_t = SRType_LSL;
5008 shift_n = 0;
5009
5010 break;
5011
5012 case eEncodingT2:
5013 // if Rn == ’1111’ then SEE LDR (literal);
5014 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5015 t = Bits32 (opcode, 15, 12);
5016 n = Bits32 (opcode, 19, 16);
5017 m = Bits32 (opcode, 3, 0);
5018
5019 // index = TRUE; add = TRUE; wback = FALSE;
5020 index = true;
5021 add = true;
5022 wback = false;
5023
5024 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5025 shift_t = SRType_LSL;
5026 shift_n = Bits32 (opcode, 5, 4);
5027
5028 // if BadReg(m) then UNPREDICTABLE;
5029 if (BadReg (m))
5030 return false;
5031
5032 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5033 if ((t == 15) && InITBlock() && !LastInITBlock())
5034 return false;
5035
5036 break;
5037
5038 case eEncodingA1:
5039 {
5040 // if P == ’0’ && W == ’1’ then SEE LDRT;
5041 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5042 t = Bits32 (opcode, 15, 12);
5043 n = Bits32 (opcode, 19, 16);
5044 m = Bits32 (opcode, 3, 0);
5045
5046 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5047 index = BitIsSet (opcode, 24);
5048 add = BitIsSet (opcode, 23);
5049 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5050
5051 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5052 uint32_t type = Bits32 (opcode, 6, 5);
5053 uint32_t imm5 = Bits32 (opcode, 11, 7);
5054 shift_n = DecodeImmShift (type, imm5, shift_t);
5055
5056 // if m == 15 then UNPREDICTABLE;
5057 if (m == 15)
5058 return false;
5059
5060 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5061 if (wback && ((n == 15) || (n == t)))
5062 return false;
5063 }
5064 break;
5065
5066
5067 default:
5068 return false;
5069 }
5070
5071 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5072 if (!success)
5073 return false;
5074
5075 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5076 if (!success)
5077 return false;
5078
5079 addr_t offset_addr;
5080 addr_t address;
5081
5082 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
5083 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
5084
5085 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5086 if (add)
5087 offset_addr = Rn + offset;
5088 else
5089 offset_addr = Rn - offset;
5090
5091 // address = if index then offset_addr else R[n];
5092 if (index)
5093 address = offset_addr;
5094 else
5095 address = Rn;
5096
5097 // data = MemU[address,4];
5098 Register base_reg;
5099 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5100
5101 EmulateInstruction::Context context;
5102 context.type = eContextRegisterLoad;
5103 context.SetRegisterPlusOffset (base_reg, address - Rn);
5104
5105 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5106 if (!success)
5107 return false;
5108
5109 // if wback then R[n] = offset_addr;
5110 if (wback)
5111 {
5112 context.type = eContextAdjustBaseRegister;
5113 context.SetAddress (offset_addr);
5114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5115 return false;
5116 }
5117
5118 // if t == 15 then
5119 if (t == 15)
5120 {
5121 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5122 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5123 {
5124 context.type = eContextRegisterLoad;
5125 context.SetRegisterPlusOffset (base_reg, address - Rn);
5126 LoadWritePC (context, data);
5127 }
5128 else
5129 return false;
5130 }
5131 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5132 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5133 {
5134 // R[t] = data;
5135 context.type = eContextRegisterLoad;
5136 context.SetRegisterPlusOffset (base_reg, address - Rn);
5137 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5138 return false;
5139 }
5140 else // Can only apply before ARMv7
5141 {
5142 // if CurrentInstrSet() == InstrSet_ARM then
5143 if (CurrentInstrSet () == eModeARM)
5144 {
5145 // R[t] = ROR(data, 8*UInt(address<1:0>));
5146 data = ROR (data, Bits32 (address, 1, 0));
5147 context.type = eContextRegisterLoad;
5148 context.SetImmediate (data);
5149 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5150 return false;
5151 }
5152 else
5153 {
5154 // R[t] = bits(32) UNKNOWN;
5155 WriteBits32Unknown (t);
5156 }
5157 }
5158 }
5159 return true;
5160}
Caroline Tice21b604b2011-02-18 21:06:04 +00005161
5162// LDRB (immediate, Thumb)
5163bool
5164EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5165{
5166#if 0
5167 if ConditionPassed() then
5168 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5169 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5170 address = if index then offset_addr else R[n];
5171 R[t] = ZeroExtend(MemU[address,1], 32);
5172 if wback then R[n] = offset_addr;
5173#endif
5174
5175 bool success = false;
5176 const uint32_t opcode = OpcodeAsUnsigned (&success);
5177 if (!success)
5178 return false;
5179
5180 if (ConditionPassed ())
5181 {
5182 uint32_t t;
5183 uint32_t n;
5184 uint32_t imm32;
5185 bool index;
5186 bool add;
5187 bool wback;
5188
5189 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5190 switch (encoding)
5191 {
5192 case eEncodingT1:
5193 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5194 t = Bits32 (opcode, 2, 0);
5195 n = Bits32 (opcode, 5, 3);
5196 imm32 = Bits32 (opcode, 10, 6);
5197
5198 // index = TRUE; add = TRUE; wback = FALSE;
5199 index = true;
5200 add = true;
5201 wback= false;
5202
5203 break;
5204
5205 case eEncodingT2:
5206 // if Rt == ’1111’ then SEE PLD;
5207 // if Rn == ’1111’ then SEE LDRB (literal);
5208 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5209 t = Bits32 (opcode, 15, 12);
5210 n = Bits32 (opcode, 19, 16);
5211 imm32 = Bits32 (opcode, 11, 0);
5212
5213 // index = TRUE; add = TRUE; wback = FALSE;
5214 index = true;
5215 add = true;
5216 wback = false;
5217
5218 // if t == 13 then UNPREDICTABLE;
5219 if (t == 13)
5220 return false;
5221
5222 break;
5223
5224 case eEncodingT3:
5225 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5226 // if Rn == ’1111’ then SEE LDRB (literal);
5227 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5228 // if P == ’0’ && W == ’0’ then UNDEFINED;
5229 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5230 return false;
5231
5232 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5233 t = Bits32 (opcode, 15, 12);
5234 n = Bits32 (opcode, 19, 16);
5235 imm32 = Bits32 (opcode, 7, 0);
5236
5237 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5238 index = BitIsSet (opcode, 10);
5239 add = BitIsSet (opcode, 9);
5240 wback = BitIsSet (opcode, 8);
5241
5242 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5243 if (BadReg (t) || (wback && (n == t)))
5244 return false;
5245
5246 break;
5247
5248 default:
5249 return false;
5250 }
5251
5252 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5253 if (!success)
5254 return false;
5255
5256 addr_t address;
5257 addr_t offset_addr;
5258
5259 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5260 if (add)
5261 offset_addr = Rn + imm32;
5262 else
5263 offset_addr = Rn - imm32;
5264
5265 // address = if index then offset_addr else R[n];
5266 if (index)
5267 address = offset_addr;
5268 else
5269 address = Rn;
5270
5271 // R[t] = ZeroExtend(MemU[address,1], 32);
5272 Register base_reg;
5273 Register data_reg;
5274 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5275 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5276
5277 EmulateInstruction::Context context;
5278 context.type = eContextRegisterLoad;
5279 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5280
5281 uint64_t data = MemURead (context, address, 1, 0, &success);
5282 if (!success)
5283 return false;
5284
5285 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5286 return false;
5287
5288 // if wback then R[n] = offset_addr;
5289 if (wback)
5290 {
5291 context.type = eContextAdjustBaseRegister;
5292 context.SetAddress (offset_addr);
5293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5294 return false;
5295 }
5296 }
5297 return true;
5298}
Caroline Ticef55261f2011-02-18 22:24:22 +00005299
5300// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5301// zero-extends it to form a 32-bit word and writes it to a register.
5302bool
5303EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5304{
5305#if 0
5306 if ConditionPassed() then
5307 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5308 base = Align(PC,4);
5309 address = if add then (base + imm32) else (base - imm32);
5310 R[t] = ZeroExtend(MemU[address,1], 32);
5311#endif
5312
5313 bool success = false;
5314 const uint32_t opcode = OpcodeAsUnsigned (&success);
5315 if (!success)
5316 return false;
5317
5318 if (ConditionPassed ())
5319 {
5320 uint32_t t;
5321 uint32_t imm32;
5322 bool add;
5323 switch (encoding)
5324 {
5325 case eEncodingT1:
5326 // if Rt == ’1111’ then SEE PLD;
5327 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5328 t = Bits32 (opcode, 15, 12);
5329 imm32 = Bits32 (opcode, 11, 0);
5330 add = BitIsSet (opcode, 23);
5331
5332 // if t == 13 then UNPREDICTABLE;
5333 if (t == 13)
5334 return false;
5335
5336 break;
5337
5338 case eEncodingA1:
5339 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5340 t = Bits32 (opcode, 15, 12);
5341 imm32 = Bits32 (opcode, 11, 0);
5342 add = BitIsSet (opcode, 23);
5343
5344 // if t == 15 then UNPREDICTABLE;
5345 if (t == 15)
5346 return false;
5347 break;
5348
5349 default:
5350 return false;
5351 }
5352
5353 // base = Align(PC,4);
5354 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5355 if (!success)
5356 return false;
5357
5358 uint32_t base = AlignPC (pc_val);
5359
5360 addr_t address;
5361 // address = if add then (base + imm32) else (base - imm32);
5362 if (add)
5363 address = base + imm32;
5364 else
5365 address = base - imm32;
5366
5367 // R[t] = ZeroExtend(MemU[address,1], 32);
5368 EmulateInstruction::Context context;
5369 context.type = eContextRelativeBranchImmediate;
5370 context.SetImmediate (address - base);
5371
5372 uint64_t data = MemURead (context, address, 1, 0, &success);
5373 if (!success)
5374 return false;
5375
5376 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5377 return false;
5378 }
5379 return true;
5380}
Caroline Tice30fec122011-02-18 23:52:21 +00005381
5382// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5383// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5384// optionally be shifted.
5385bool
5386EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5387{
5388#if 0
5389 if ConditionPassed() then
5390 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5391 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5392 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5393 address = if index then offset_addr else R[n];
5394 R[t] = ZeroExtend(MemU[address,1],32);
5395 if wback then R[n] = offset_addr;
5396#endif
5397
5398 bool success = false;
5399 const uint32_t opcode = OpcodeAsUnsigned (&success);
5400 if (!success)
5401 return false;
5402
5403 if (ConditionPassed ())
5404 {
5405 uint32_t t;
5406 uint32_t n;
5407 uint32_t m;
5408 bool index;
5409 bool add;
5410 bool wback;
5411 ARM_ShifterType shift_t;
5412 uint32_t shift_n;
5413
5414 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5415 switch (encoding)
5416 {
5417 case eEncodingT1:
5418 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5419 t = Bits32 (opcode, 2, 0);
5420 n = Bits32 (opcode, 5, 3);
5421 m = Bits32 (opcode, 8, 6);
5422
5423 // index = TRUE; add = TRUE; wback = FALSE;
5424 index = true;
5425 add = true;
5426 wback = false;
5427
5428 // (shift_t, shift_n) = (SRType_LSL, 0);
5429 shift_t = SRType_LSL;
5430 shift_n = 0;
5431 break;
5432
5433 case eEncodingT2:
5434 // if Rt == ’1111’ then SEE PLD;
5435 // if Rn == ’1111’ then SEE LDRB (literal);
5436 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5437 t = Bits32 (opcode, 15, 12);
5438 n = Bits32 (opcode, 19, 16);
5439 m = Bits32 (opcode, 3, 0);
5440
5441 // index = TRUE; add = TRUE; wback = FALSE;
5442 index = true;
5443 add = true;
5444 wback = false;
5445
5446 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5447 shift_t = SRType_LSL;
5448 shift_n = Bits32 (opcode, 5, 4);
5449
5450 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5451 if ((t == 13) || BadReg (m))
5452 return false;
5453 break;
5454
5455 case eEncodingA1:
5456 {
5457 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5458 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5459 t = Bits32 (opcode, 15, 12);
5460 n = Bits32 (opcode, 19, 16);
5461 m = Bits32 (opcode, 3, 0);
5462
5463 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5464 index = BitIsSet (opcode, 24);
5465 add = BitIsSet (opcode, 23);
5466 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5467
5468 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5469 uint32_t type = Bits32 (opcode, 6, 5);
5470 uint32_t imm5 = Bits32 (opcode, 11, 7);
5471 shift_n = DecodeImmShift (type, imm5, shift_t);
5472
5473 // if t == 15 || m == 15 then UNPREDICTABLE;
5474 if ((t == 15) || (m == 15))
5475 return false;
5476
5477 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5478 if (wback && ((n == 15) || (n == t)))
5479 return false;
5480 }
5481 break;
5482
5483 default:
5484 return false;
5485 }
5486
5487 addr_t offset_addr;
5488 addr_t address;
5489
5490 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5491 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5492 if (!success)
5493 return false;
5494
5495 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5496
5497 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5498 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5499 if (!success)
5500 return false;
5501
5502 if (add)
5503 offset_addr = Rn + offset;
5504 else
5505 offset_addr = Rn - offset;
5506
5507 // address = if index then offset_addr else R[n];
5508 if (index)
5509 address = offset_addr;
5510 else
5511 address = Rn;
5512
5513 // R[t] = ZeroExtend(MemU[address,1],32);
5514 Register base_reg;
5515 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5516
5517 EmulateInstruction::Context context;
5518 context.type = eContextRegisterLoad;
5519 context.SetRegisterPlusOffset (base_reg, address - Rn);
5520
5521 uint64_t data = MemURead (context, address, 1, 0, &success);
5522 if (!success)
5523 return false;
5524
5525 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5526 return false;
5527
5528 // if wback then R[n] = offset_addr;
5529 if (wback)
5530 {
5531 context.type = eContextAdjustBaseRegister;
5532 context.SetAddress (offset_addr);
5533 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5534 return false;
5535 }
5536 }
5537 return true;
5538}
Caroline Ticefe479112011-02-18 18:52:37 +00005539
Johnny Chen2115b412011-02-21 23:42:44 +00005540// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5541// and writes the result to the destination register. It can optionally update the condition flags based on
5542// the result.
5543bool
5544EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5545{
5546#if 0
5547 // ARM pseudo code...
5548 if ConditionPassed() then
5549 EncodingSpecificOperations();
5550 result = R[n] EOR imm32;
5551 if d == 15 then // Can only occur for ARM encoding
5552 ALUWritePC(result); // setflags is always FALSE here
5553 else
5554 R[d] = result;
5555 if setflags then
5556 APSR.N = result<31>;
5557 APSR.Z = IsZeroBit(result);
5558 APSR.C = carry;
5559 // APSR.V unchanged
5560#endif
5561
5562 bool success = false;
5563 const uint32_t opcode = OpcodeAsUnsigned (&success);
5564 if (!success)
5565 return false;
5566
5567 if (ConditionPassed())
5568 {
5569 uint32_t Rd, Rn;
5570 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5571 bool setflags;
5572 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5573 switch (encoding)
5574 {
5575 case eEncodingT1:
5576 Rd = Bits32(opcode, 11, 8);
5577 Rn = Bits32(opcode, 19, 16);
5578 setflags = BitIsSet(opcode, 20);
5579 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5580 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5581 if (Rd == 15 && setflags)
5582 return EmulateTEQImm(eEncodingT1);
5583 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5584 return false;
5585 break;
5586 case eEncodingA1:
5587 Rd = Bits32(opcode, 15, 12);
5588 Rn = Bits32(opcode, 19, 16);
5589 setflags = BitIsSet(opcode, 20);
5590 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5591 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5592 // TODO: Emulate SUBS PC, LR and related instructions.
5593 if (Rd == 15 && setflags)
5594 return false;
5595 break;
5596 default:
5597 return false;
5598 }
5599
5600 // Read the first operand.
5601 uint32_t val1 = ReadCoreReg(Rn, &success);
5602 if (!success)
5603 return false;
5604
5605 uint32_t result = val1 ^ imm32;
5606
5607 EmulateInstruction::Context context;
5608 context.type = EmulateInstruction::eContextImmediate;
5609 context.SetNoArgs ();
5610
5611 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5612 return false;
5613 }
5614 return true;
5615}
5616
5617// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5618// optionally-shifted register value, and writes the result to the destination register.
5619// It can optionally update the condition flags based on the result.
5620bool
5621EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5622{
5623#if 0
5624 // ARM pseudo code...
5625 if ConditionPassed() then
5626 EncodingSpecificOperations();
5627 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5628 result = R[n] EOR shifted;
5629 if d == 15 then // Can only occur for ARM encoding
5630 ALUWritePC(result); // setflags is always FALSE here
5631 else
5632 R[d] = result;
5633 if setflags then
5634 APSR.N = result<31>;
5635 APSR.Z = IsZeroBit(result);
5636 APSR.C = carry;
5637 // APSR.V unchanged
5638#endif
5639
5640 bool success = false;
5641 const uint32_t opcode = OpcodeAsUnsigned (&success);
5642 if (!success)
5643 return false;
5644
5645 if (ConditionPassed())
5646 {
5647 uint32_t Rd, Rn, Rm;
5648 ARM_ShifterType shift_t;
5649 uint32_t shift_n; // the shift applied to the value read from Rm
5650 bool setflags;
5651 uint32_t carry;
5652 switch (encoding)
5653 {
5654 case eEncodingT1:
5655 Rd = Rn = Bits32(opcode, 2, 0);
5656 Rm = Bits32(opcode, 5, 3);
5657 setflags = !InITBlock();
5658 shift_t = SRType_LSL;
5659 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005660 break;
Johnny Chen2115b412011-02-21 23:42:44 +00005661 case eEncodingT2:
5662 Rd = Bits32(opcode, 11, 8);
5663 Rn = Bits32(opcode, 19, 16);
5664 Rm = Bits32(opcode, 3, 0);
5665 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005666 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5667 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005668 if (Rd == 15 && setflags)
5669 return EmulateTEQReg(eEncodingT1);
5670 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5671 return false;
5672 break;
5673 case eEncodingA1:
5674 Rd = Bits32(opcode, 15, 12);
5675 Rn = Bits32(opcode, 19, 16);
5676 Rm = Bits32(opcode, 3, 0);
5677 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005678 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005679 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5680 // TODO: Emulate SUBS PC, LR and related instructions.
5681 if (Rd == 15 && setflags)
5682 return false;
5683 break;
5684 default:
5685 return false;
5686 }
5687
5688 // Read the first operand.
5689 uint32_t val1 = ReadCoreReg(Rn, &success);
5690 if (!success)
5691 return false;
5692
5693 // Read the second operand.
5694 uint32_t val2 = ReadCoreReg(Rm, &success);
5695 if (!success)
5696 return false;
5697
5698 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5699 uint32_t result = val1 ^ shifted;
5700
5701 EmulateInstruction::Context context;
5702 context.type = EmulateInstruction::eContextImmediate;
5703 context.SetNoArgs ();
5704
5705 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5706 return false;
5707 }
5708 return true;
5709}
5710
Johnny Chen7c5234d2011-02-18 23:41:11 +00005711// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5712// writes the result to the destination register. It can optionally update the condition flags based
5713// on the result.
5714bool
5715EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5716{
5717#if 0
5718 // ARM pseudo code...
5719 if ConditionPassed() then
5720 EncodingSpecificOperations();
5721 result = R[n] OR imm32;
5722 if d == 15 then // Can only occur for ARM encoding
5723 ALUWritePC(result); // setflags is always FALSE here
5724 else
5725 R[d] = result;
5726 if setflags then
5727 APSR.N = result<31>;
5728 APSR.Z = IsZeroBit(result);
5729 APSR.C = carry;
5730 // APSR.V unchanged
5731#endif
5732
5733 bool success = false;
5734 const uint32_t opcode = OpcodeAsUnsigned (&success);
5735 if (!success)
5736 return false;
5737
5738 if (ConditionPassed())
5739 {
5740 uint32_t Rd, Rn;
5741 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5742 bool setflags;
5743 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5744 switch (encoding)
5745 {
5746 case eEncodingT1:
5747 Rd = Bits32(opcode, 11, 8);
5748 Rn = Bits32(opcode, 19, 16);
5749 setflags = BitIsSet(opcode, 20);
5750 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5751 // if Rn == ‘1111’ then SEE MOV (immediate);
5752 if (Rn == 15)
5753 return EmulateMOVRdImm(eEncodingT2);
5754 if (BadReg(Rd) || Rn == 13)
5755 return false;
5756 break;
5757 case eEncodingA1:
5758 Rd = Bits32(opcode, 15, 12);
5759 Rn = Bits32(opcode, 19, 16);
5760 setflags = BitIsSet(opcode, 20);
5761 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5762 // TODO: Emulate SUBS PC, LR and related instructions.
5763 if (Rd == 15 && setflags)
5764 return false;
5765 break;
5766 default:
5767 return false;
5768 }
5769
5770 // Read the first operand.
5771 uint32_t val1 = ReadCoreReg(Rn, &success);
5772 if (!success)
5773 return false;
5774
5775 uint32_t result = val1 | imm32;
5776
5777 EmulateInstruction::Context context;
5778 context.type = EmulateInstruction::eContextImmediate;
5779 context.SetNoArgs ();
5780
5781 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5782 return false;
5783 }
5784 return true;
5785}
5786
5787// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5788// value, and writes the result to the destination register. It can optionally update the condition flags based
5789// on the result.
5790bool
5791EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5792{
5793#if 0
5794 // ARM pseudo code...
5795 if ConditionPassed() then
5796 EncodingSpecificOperations();
5797 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5798 result = R[n] OR shifted;
5799 if d == 15 then // Can only occur for ARM encoding
5800 ALUWritePC(result); // setflags is always FALSE here
5801 else
5802 R[d] = result;
5803 if setflags then
5804 APSR.N = result<31>;
5805 APSR.Z = IsZeroBit(result);
5806 APSR.C = carry;
5807 // APSR.V unchanged
5808#endif
5809
5810 bool success = false;
5811 const uint32_t opcode = OpcodeAsUnsigned (&success);
5812 if (!success)
5813 return false;
5814
5815 if (ConditionPassed())
5816 {
5817 uint32_t Rd, Rn, Rm;
5818 ARM_ShifterType shift_t;
5819 uint32_t shift_n; // the shift applied to the value read from Rm
5820 bool setflags;
5821 uint32_t carry;
5822 switch (encoding)
5823 {
5824 case eEncodingT1:
5825 Rd = Rn = Bits32(opcode, 2, 0);
5826 Rm = Bits32(opcode, 5, 3);
5827 setflags = !InITBlock();
5828 shift_t = SRType_LSL;
5829 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005830 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005831 case eEncodingT2:
5832 Rd = Bits32(opcode, 11, 8);
5833 Rn = Bits32(opcode, 19, 16);
5834 Rm = Bits32(opcode, 3, 0);
5835 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005836 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5837 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005838 if (Rn == 15)
5839 return EmulateMOVRdRm(eEncodingT3);
5840 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5841 return false;
5842 break;
5843 case eEncodingA1:
5844 Rd = Bits32(opcode, 15, 12);
5845 Rn = Bits32(opcode, 19, 16);
5846 Rm = Bits32(opcode, 3, 0);
5847 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005848 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005849 // TODO: Emulate SUBS PC, LR and related instructions.
5850 if (Rd == 15 && setflags)
5851 return false;
5852 break;
5853 default:
5854 return false;
5855 }
5856
5857 // Read the first operand.
5858 uint32_t val1 = ReadCoreReg(Rn, &success);
5859 if (!success)
5860 return false;
5861
5862 // Read the second operand.
5863 uint32_t val2 = ReadCoreReg(Rm, &success);
5864 if (!success)
5865 return false;
5866
5867 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005868 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005869
5870 EmulateInstruction::Context context;
5871 context.type = EmulateInstruction::eContextImmediate;
5872 context.SetNoArgs ();
5873
5874 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5875 return false;
5876 }
5877 return true;
5878}
5879
Johnny Chened32e7c2011-02-22 23:42:58 +00005880// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
5881// the destination register. It can optionally update the condition flags based on the result.
5882bool
5883EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
5884{
5885#if 0
5886 // ARM pseudo code...
5887 if ConditionPassed() then
5888 EncodingSpecificOperations();
5889 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
5890 if d == 15 then // Can only occur for ARM encoding
5891 ALUWritePC(result); // setflags is always FALSE here
5892 else
5893 R[d] = result;
5894 if setflags then
5895 APSR.N = result<31>;
5896 APSR.Z = IsZeroBit(result);
5897 APSR.C = carry;
5898 APSR.V = overflow;
5899#endif
5900
5901 bool success = false;
5902 const uint32_t opcode = OpcodeAsUnsigned (&success);
5903 if (!success)
5904 return false;
5905
5906 uint32_t Rd; // the destination register
5907 uint32_t Rn; // the first operand
5908 bool setflags;
5909 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5910 switch (encoding) {
5911 case eEncodingT1:
5912 Rd = Bits32(opcode, 2, 0);
5913 Rn = Bits32(opcode, 5, 3);
5914 setflags = !InITBlock();
5915 imm32 = 0;
5916 break;
5917 case eEncodingT2:
5918 Rd = Bits32(opcode, 11, 8);
5919 Rn = Bits32(opcode, 19, 16);
5920 setflags = BitIsSet(opcode, 20);
5921 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5922 if (BadReg(Rd) || BadReg(Rn))
5923 return false;
5924 break;
5925 case eEncodingA1:
5926 Rd = Bits32(opcode, 15, 12);
5927 Rn = Bits32(opcode, 19, 16);
5928 setflags = BitIsSet(opcode, 20);
5929 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5930 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5931 // TODO: Emulate SUBS PC, LR and related instructions.
5932 if (Rd == 15 && setflags)
5933 return false;
5934 break;
5935 default:
5936 return false;
5937 }
5938 // Read the register value from the operand register Rn.
5939 uint32_t reg_val = ReadCoreReg(Rn, &success);
5940 if (!success)
5941 return false;
5942
5943 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
5944
5945 EmulateInstruction::Context context;
5946 context.type = EmulateInstruction::eContextImmediate;
5947 context.SetNoArgs ();
5948
5949 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5950 return false;
5951
5952 return true;
5953}
5954
5955// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
5956// result to the destination register. It can optionally update the condition flags based on the result.
5957bool
5958EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
5959{
5960#if 0
5961 // ARM pseudo code...
5962 if ConditionPassed() then
5963 EncodingSpecificOperations();
5964 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5965 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
5966 if d == 15 then // Can only occur for ARM encoding
5967 ALUWritePC(result); // setflags is always FALSE here
5968 else
5969 R[d] = result;
5970 if setflags then
5971 APSR.N = result<31>;
5972 APSR.Z = IsZeroBit(result);
5973 APSR.C = carry;
5974 APSR.V = overflow;
5975#endif
5976
5977 bool success = false;
5978 const uint32_t opcode = OpcodeAsUnsigned (&success);
5979 if (!success)
5980 return false;
5981
5982 uint32_t Rd; // the destination register
5983 uint32_t Rn; // the first operand
5984 uint32_t Rm; // the second operand
5985 bool setflags;
5986 ARM_ShifterType shift_t;
5987 uint32_t shift_n; // the shift applied to the value read from Rm
5988 switch (encoding) {
5989 case eEncodingT1:
5990 Rd = Bits32(opcode, 11, 8);
5991 Rn = Bits32(opcode, 19, 16);
5992 Rm = Bits32(opcode, 3, 0);
5993 setflags = BitIsSet(opcode, 20);
5994 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5995 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
5996 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5997 return false;
5998 break;
5999 case eEncodingA1:
6000 Rd = Bits32(opcode, 15, 12);
6001 Rn = Bits32(opcode, 19, 16);
6002 Rm = Bits32(opcode, 3, 0);
6003 setflags = BitIsSet(opcode, 20);
6004 shift_n = DecodeImmShiftARM(opcode, shift_t);
6005 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6006 // TODO: Emulate SUBS PC, LR and related instructions.
6007 if (Rd == 15 && setflags)
6008 return false;
6009 break;
6010 default:
6011 return false;
6012 }
6013 // Read the register value from register Rn.
6014 uint32_t val1 = ReadCoreReg(Rn, &success);
6015 if (!success)
6016 return false;
6017
6018 // Read the register value from register Rm.
6019 uint32_t val2 = ReadCoreReg(Rm, &success);
6020 if (!success)
6021 return false;
6022
6023 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6024 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6025
6026 EmulateInstruction::Context context;
6027 context.type = EmulateInstruction::eContextImmediate;
6028 context.SetNoArgs();
6029 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6030 return false;
6031
6032 return true;
6033}
6034
Johnny Chen2115b412011-02-21 23:42:44 +00006035// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
6036// immediate value. It updates the condition flags based on the result, and discards the result.
6037bool
6038EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
6039{
6040#if 0
6041 // ARM pseudo code...
6042 if ConditionPassed() then
6043 EncodingSpecificOperations();
6044 result = R[n] EOR imm32;
6045 APSR.N = result<31>;
6046 APSR.Z = IsZeroBit(result);
6047 APSR.C = carry;
6048 // APSR.V unchanged
6049#endif
6050
6051 bool success = false;
6052 const uint32_t opcode = OpcodeAsUnsigned (&success);
6053 if (!success)
6054 return false;
6055
6056 if (ConditionPassed())
6057 {
6058 uint32_t Rn;
6059 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6060 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6061 switch (encoding)
6062 {
6063 case eEncodingT1:
6064 Rn = Bits32(opcode, 19, 16);
6065 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6066 if (BadReg(Rn))
6067 return false;
6068 break;
6069 case eEncodingA1:
6070 Rn = Bits32(opcode, 19, 16);
6071 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6072 break;
6073 default:
6074 return false;
6075 }
6076
6077 // Read the first operand.
6078 uint32_t val1 = ReadCoreReg(Rn, &success);
6079 if (!success)
6080 return false;
6081
6082 uint32_t result = val1 ^ imm32;
6083
6084 EmulateInstruction::Context context;
6085 context.type = EmulateInstruction::eContextImmediate;
6086 context.SetNoArgs ();
6087
6088 if (!WriteFlags(context, result, carry))
6089 return false;
6090 }
6091 return true;
6092}
6093
6094// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
6095// optionally-shifted register value. It updates the condition flags based on the result, and discards
6096// the result.
6097bool
6098EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
6099{
6100#if 0
6101 // ARM pseudo code...
6102 if ConditionPassed() then
6103 EncodingSpecificOperations();
6104 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6105 result = R[n] EOR shifted;
6106 APSR.N = result<31>;
6107 APSR.Z = IsZeroBit(result);
6108 APSR.C = carry;
6109 // APSR.V unchanged
6110#endif
6111
6112 bool success = false;
6113 const uint32_t opcode = OpcodeAsUnsigned (&success);
6114 if (!success)
6115 return false;
6116
6117 if (ConditionPassed())
6118 {
6119 uint32_t Rn, Rm;
6120 ARM_ShifterType shift_t;
6121 uint32_t shift_n; // the shift applied to the value read from Rm
6122 uint32_t carry;
6123 switch (encoding)
6124 {
6125 case eEncodingT1:
6126 Rn = Bits32(opcode, 19, 16);
6127 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006128 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006129 if (BadReg(Rn) || BadReg(Rm))
6130 return false;
6131 break;
6132 case eEncodingA1:
6133 Rn = Bits32(opcode, 19, 16);
6134 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006135 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006136 break;
6137 default:
6138 return false;
6139 }
6140
6141 // Read the first operand.
6142 uint32_t val1 = ReadCoreReg(Rn, &success);
6143 if (!success)
6144 return false;
6145
6146 // Read the second operand.
6147 uint32_t val2 = ReadCoreReg(Rm, &success);
6148 if (!success)
6149 return false;
6150
6151 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6152 uint32_t result = val1 ^ shifted;
6153
6154 EmulateInstruction::Context context;
6155 context.type = EmulateInstruction::eContextImmediate;
6156 context.SetNoArgs ();
6157
6158 if (!WriteFlags(context, result, carry))
6159 return false;
6160 }
6161 return true;
6162}
6163
Johnny Chende3cce32011-02-21 21:24:49 +00006164// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
6165// It updates the condition flags based on the result, and discards the result.
6166bool
6167EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6168{
6169#if 0
6170 // ARM pseudo code...
6171 if ConditionPassed() then
6172 EncodingSpecificOperations();
6173 result = R[n] AND imm32;
6174 APSR.N = result<31>;
6175 APSR.Z = IsZeroBit(result);
6176 APSR.C = carry;
6177 // APSR.V unchanged
6178#endif
6179
6180 bool success = false;
6181 const uint32_t opcode = OpcodeAsUnsigned (&success);
6182 if (!success)
6183 return false;
6184
6185 if (ConditionPassed())
6186 {
6187 uint32_t Rn;
6188 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6189 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6190 switch (encoding)
6191 {
6192 case eEncodingT1:
6193 Rn = Bits32(opcode, 19, 16);
6194 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6195 if (BadReg(Rn))
6196 return false;
6197 break;
6198 case eEncodingA1:
6199 Rn = Bits32(opcode, 19, 16);
6200 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6201 break;
6202 default:
6203 return false;
6204 }
6205
6206 // Read the first operand.
6207 uint32_t val1 = ReadCoreReg(Rn, &success);
6208 if (!success)
6209 return false;
6210
6211 uint32_t result = val1 & imm32;
6212
6213 EmulateInstruction::Context context;
6214 context.type = EmulateInstruction::eContextImmediate;
6215 context.SetNoArgs ();
6216
6217 if (!WriteFlags(context, result, carry))
6218 return false;
6219 }
6220 return true;
6221}
6222
6223// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6224// It updates the condition flags based on the result, and discards the result.
6225bool
6226EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6227{
6228#if 0
6229 // ARM pseudo code...
6230 if ConditionPassed() then
6231 EncodingSpecificOperations();
6232 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6233 result = R[n] AND shifted;
6234 APSR.N = result<31>;
6235 APSR.Z = IsZeroBit(result);
6236 APSR.C = carry;
6237 // APSR.V unchanged
6238#endif
6239
6240 bool success = false;
6241 const uint32_t opcode = OpcodeAsUnsigned (&success);
6242 if (!success)
6243 return false;
6244
6245 if (ConditionPassed())
6246 {
6247 uint32_t Rn, Rm;
6248 ARM_ShifterType shift_t;
6249 uint32_t shift_n; // the shift applied to the value read from Rm
6250 uint32_t carry;
6251 switch (encoding)
6252 {
6253 case eEncodingT1:
6254 Rn = Bits32(opcode, 2, 0);
6255 Rm = Bits32(opcode, 5, 3);
6256 shift_t = SRType_LSL;
6257 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006258 break;
Johnny Chende3cce32011-02-21 21:24:49 +00006259 case eEncodingT2:
6260 Rn = Bits32(opcode, 19, 16);
6261 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006262 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006263 if (BadReg(Rn) || BadReg(Rm))
6264 return false;
6265 break;
6266 case eEncodingA1:
6267 Rn = Bits32(opcode, 19, 16);
6268 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006269 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006270 break;
6271 default:
6272 return false;
6273 }
6274
6275 // Read the first operand.
6276 uint32_t val1 = ReadCoreReg(Rn, &success);
6277 if (!success)
6278 return false;
6279
6280 // Read the second operand.
6281 uint32_t val2 = ReadCoreReg(Rm, &success);
6282 if (!success)
6283 return false;
6284
6285 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6286 uint32_t result = val1 & shifted;
6287
6288 EmulateInstruction::Context context;
6289 context.type = EmulateInstruction::eContextImmediate;
6290 context.SetNoArgs ();
6291
6292 if (!WriteFlags(context, result, carry))
6293 return false;
6294 }
6295 return true;
6296}
6297
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006298EmulateInstructionARM::ARMOpcode*
6299EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006300{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006301 static ARMOpcode
6302 g_arm_opcodes[] =
6303 {
6304 //----------------------------------------------------------------------
6305 // Prologue instructions
6306 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006307
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006308 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006309 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6310 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006311
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006312 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006313 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006314 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006315 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006316 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6317 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006318 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006319
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006320 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006321 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006322
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006323 // push one register
6324 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006325 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006326
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006327 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006328 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6329 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006330
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006331 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006332 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006333 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006334
Johnny Chen9f687722011-02-18 00:02:28 +00006335 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6336 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006337 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006338 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6339
6340 //----------------------------------------------------------------------
6341 // Supervisor Call (previously Software Interrupt)
6342 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006343 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6344
6345 //----------------------------------------------------------------------
6346 // Branch instructions
6347 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006348 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006349 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6350 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6351 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6352 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006353 // for example, "bx lr"
6354 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006355
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006356 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006357 // Data-processing instructions
6358 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006359 // adc (immediate)
6360 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6361 // adc (register)
6362 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006363 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006364 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006365 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006366 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006367 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006368 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006369 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006370 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006371 // eor (immediate)
6372 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6373 // eor (register)
6374 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006375 // orr (immediate)
6376 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6377 // orr (register)
6378 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006379 // rsb (immediate)
6380 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
6381 // rsb (register)
6382 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006383 // teq (immediate)
6384 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6385 // teq (register)
6386 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006387 // tst (immediate)
6388 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6389 // tst (register)
6390 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6391
6392
Johnny Chend642a6a2011-02-22 01:01:03 +00006393 // mvn (immediate)
6394 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6395 // mvn (register)
6396 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006397 // cmn (immediate)
6398 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6399 // cmn (register)
6400 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006401 // cmp (immediate)
6402 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6403 // cmp (register)
6404 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006405 // asr (immediate)
6406 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006407 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006408 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006409 // lsl (immediate)
6410 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6411 // lsl (register)
6412 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6413 // lsr (immediate)
6414 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6415 // lsr (register)
6416 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006417 // rrx is a special case encoding of ror (immediate)
6418 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6419 // ror (immediate)
6420 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6421 // ror (register)
6422 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006423
6424 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006425 // Load instructions
6426 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006427 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006428 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006429 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006430 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006431 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006432 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00006433 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
6434 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00006435
6436 //----------------------------------------------------------------------
6437 // Store instructions
6438 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00006439 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006440 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00006441 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00006442 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
6443 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00006444
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006445
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006446 };
6447 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
6448
6449 for (size_t i=0; i<k_num_arm_opcodes; ++i)
6450 {
6451 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
6452 return &g_arm_opcodes[i];
6453 }
6454 return NULL;
6455}
Greg Clayton64c84432011-01-21 22:02:52 +00006456
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006457
6458EmulateInstructionARM::ARMOpcode*
6459EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00006460{
Johnny Chenfdd179e2011-01-31 20:09:28 +00006461
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006462 static ARMOpcode
6463 g_thumb_opcodes[] =
6464 {
6465 //----------------------------------------------------------------------
6466 // Prologue instructions
6467 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00006468
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006469 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006470 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6471 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
6472 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00006473
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006474 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006475 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006476 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00006477 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006478 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00006479 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00006480
Johnny Chen864a8e82011-02-18 00:07:39 +00006481 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00006482 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00006483
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006484 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006485 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
6486 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
6487 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
6488 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006489
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006490 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00006491 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6492 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006493
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006494 //----------------------------------------------------------------------
6495 // Epilogue instructions
6496 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00006497
Johnny Chen864a8e82011-02-18 00:07:39 +00006498 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00006499 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6500 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
6501 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00006502 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
6503 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006504
6505 //----------------------------------------------------------------------
6506 // Supervisor Call (previously Software Interrupt)
6507 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00006508 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
6509
6510 //----------------------------------------------------------------------
6511 // If Then makes up to four following instructions conditional.
6512 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006513 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
6514
6515 //----------------------------------------------------------------------
6516 // Branch instructions
6517 //----------------------------------------------------------------------
6518 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
6519 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
6520 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00006521 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006522 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00006523 // J1 == J2 == 1
6524 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6525 // J1 == J2 == 1
6526 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6527 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006528 // for example, "bx lr"
6529 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00006530 // compare and branch
6531 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00006532 // table branch byte
6533 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
6534 // table branch halfword
6535 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006536
6537 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00006538 // Data-processing instructions
6539 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006540 // adc (immediate)
6541 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
6542 // adc (register)
6543 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
6544 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
6545 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00006546 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006547 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00006548 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006549 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006550 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006551 // and (register)
6552 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
6553 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006554 // eor (immediate)
6555 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
6556 // eor (register)
6557 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
6558 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006559 // orr (immediate)
6560 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
6561 // orr (register)
6562 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
6563 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006564 // rsb (immediate)
6565 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
6566 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
6567 // rsb (register)
6568 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006569 // teq (immediate)
6570 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
6571 // teq (register)
6572 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006573 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00006574 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00006575 // tst (register)
6576 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
6577 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
6578
Johnny Chen7c5234d2011-02-18 23:41:11 +00006579
Johnny Chen338bf542011-02-10 19:29:03 +00006580 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00006581 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00006582 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00006583 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006584 // mov{s}<c>.w <Rd>, <Rm>
6585 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00006586 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00006587 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
6588 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00006589 // mvn (immediate)
6590 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
6591 // mvn (register)
6592 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
6593 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006594 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00006595 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006596 // cmn (register)
6597 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006598 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006599 // cmp (immediate)
6600 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006601 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006602 // cmp (register) (Rn and Rm both from r0-r7)
6603 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
6604 // cmp (register) (Rn and Rm not both from r0-r7)
6605 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006606 // asr (immediate)
6607 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00006608 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00006609 // asr (register)
6610 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
6611 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006612 // lsl (immediate)
6613 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
6614 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
6615 // lsl (register)
6616 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
6617 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
6618 // lsr (immediate)
6619 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
6620 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
6621 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00006622 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006623 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006624 // rrx is a special case encoding of ror (immediate)
6625 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
6626 // ror (immediate)
6627 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
6628 // ror (register)
6629 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
6630 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006631
6632 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006633 // Load instructions
6634 //----------------------------------------------------------------------
6635 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00006636 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00006637 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00006638 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
6639 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00006640 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00006641 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
6642 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00006643 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
6644 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
6645 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00006646 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00006647 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
6648 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00006649
6650 //----------------------------------------------------------------------
6651 // Store instructions
6652 //----------------------------------------------------------------------
6653 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006654 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00006655 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00006656 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
6657 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
6658 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
6659 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
6660 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
6661 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
6662 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
6663 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
6664 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006665 };
6666
6667 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
6668 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
6669 {
6670 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
6671 return &g_thumb_opcodes[i];
6672 }
6673 return NULL;
6674}
Greg Clayton64c84432011-01-21 22:02:52 +00006675
Greg Clayton31e2a382011-01-30 20:03:56 +00006676bool
Greg Clayton395fc332011-02-15 21:59:32 +00006677EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00006678{
6679 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00006680 const char *arch_cstr = arch.AsCString ();
6681 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00006682 {
Greg Clayton395fc332011-02-15 21:59:32 +00006683 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
6684 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
6685 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
6686 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
6687 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
6688 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
6689 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
6690 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
6691 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
6692 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00006693 }
6694 return m_arm_isa != 0;
6695}
6696
6697
Greg Clayton64c84432011-01-21 22:02:52 +00006698bool
6699EmulateInstructionARM::ReadInstruction ()
6700{
6701 bool success = false;
6702 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
6703 if (success)
6704 {
6705 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
6706 if (success)
6707 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00006708 Context read_inst_context;
6709 read_inst_context.type = eContextReadOpcode;
6710 read_inst_context.SetNoArgs ();
6711
Greg Clayton64c84432011-01-21 22:02:52 +00006712 if (m_inst_cpsr & MASK_CPSR_T)
6713 {
6714 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006715 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006716
6717 if (success)
6718 {
6719 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
6720 {
6721 m_inst.opcode_type = eOpcode16;
6722 m_inst.opcode.inst16 = thumb_opcode;
6723 }
6724 else
6725 {
6726 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006727 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006728 }
6729 }
6730 }
6731 else
6732 {
6733 m_inst_mode = eModeARM;
6734 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006735 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006736 }
6737 }
6738 }
6739 if (!success)
6740 {
6741 m_inst_mode = eModeInvalid;
6742 m_inst_pc = LLDB_INVALID_ADDRESS;
6743 }
6744 return success;
6745}
6746
Johnny Chenee9b1f72011-02-09 01:00:31 +00006747uint32_t
6748EmulateInstructionARM::ArchVersion ()
6749{
6750 return m_arm_isa;
6751}
6752
Greg Clayton64c84432011-01-21 22:02:52 +00006753bool
6754EmulateInstructionARM::ConditionPassed ()
6755{
6756 if (m_inst_cpsr == 0)
6757 return false;
6758
6759 const uint32_t cond = CurrentCond ();
6760
6761 if (cond == UINT32_MAX)
6762 return false;
6763
6764 bool result = false;
6765 switch (UnsignedBits(cond, 3, 1))
6766 {
6767 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
6768 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
6769 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
6770 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
6771 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
6772 case 5:
6773 {
6774 bool n = (m_inst_cpsr & MASK_CPSR_N);
6775 bool v = (m_inst_cpsr & MASK_CPSR_V);
6776 result = n == v;
6777 }
6778 break;
6779 case 6:
6780 {
6781 bool n = (m_inst_cpsr & MASK_CPSR_N);
6782 bool v = (m_inst_cpsr & MASK_CPSR_V);
6783 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
6784 }
6785 break;
6786 case 7:
6787 result = true;
6788 break;
6789 }
6790
6791 if (cond & 1)
6792 result = !result;
6793 return result;
6794}
6795
Johnny Chen9ee056b2011-02-08 00:06:35 +00006796uint32_t
6797EmulateInstructionARM::CurrentCond ()
6798{
6799 switch (m_inst_mode)
6800 {
6801 default:
6802 case eModeInvalid:
6803 break;
6804
6805 case eModeARM:
6806 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
6807
6808 case eModeThumb:
6809 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
6810 // 'cond' field of the encoding.
6811 if (m_inst.opcode_type == eOpcode16 &&
6812 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
6813 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
6814 {
6815 return Bits32(m_inst.opcode.inst16, 11, 7);
6816 }
6817 else if (m_inst.opcode_type == eOpcode32 &&
6818 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
6819 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
6820 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
6821 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
6822 {
6823 return Bits32(m_inst.opcode.inst32, 25, 22);
6824 }
6825
6826 return m_it_session.GetCond();
6827 }
6828 return UINT32_MAX; // Return invalid value
6829}
6830
Johnny Chen9ee056b2011-02-08 00:06:35 +00006831bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00006832EmulateInstructionARM::InITBlock()
6833{
6834 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
6835}
6836
6837bool
6838EmulateInstructionARM::LastInITBlock()
6839{
6840 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
6841}
6842
6843bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00006844EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
6845{
6846 addr_t target;
6847
Johnny Chenee9b1f72011-02-09 01:00:31 +00006848 // Check the current instruction set.
6849 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006850 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006851 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00006852 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006853
Johnny Chen9ee056b2011-02-08 00:06:35 +00006854 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006855 return false;
6856
6857 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006858}
6859
6860// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
6861bool
Johnny Chen668b4512011-02-15 21:08:58 +00006862EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006863{
6864 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00006865 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
6866 // we want to record it and issue a WriteRegister callback so the clients
6867 // can track the mode changes accordingly.
6868 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006869
6870 if (BitIsSet(addr, 0))
6871 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006872 if (CurrentInstrSet() != eModeThumb)
6873 {
6874 SelectInstrSet(eModeThumb);
6875 cpsr_changed = true;
6876 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006877 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00006878 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006879 }
6880 else if (BitIsClear(addr, 1))
6881 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006882 if (CurrentInstrSet() != eModeARM)
6883 {
6884 SelectInstrSet(eModeARM);
6885 cpsr_changed = true;
6886 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006887 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00006888 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006889 }
6890 else
6891 return false; // address<1:0> == '10' => UNPREDICTABLE
6892
Johnny Chen0f309db2011-02-09 19:11:32 +00006893 if (cpsr_changed)
6894 {
Johnny Chen558133b2011-02-09 23:59:17 +00006895 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00006896 return false;
6897 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006898 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006899 return false;
6900
6901 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006902}
Greg Clayton64c84432011-01-21 22:02:52 +00006903
Johnny Chenee9b1f72011-02-09 01:00:31 +00006904// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
6905bool
Johnny Chen668b4512011-02-15 21:08:58 +00006906EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00006907{
6908 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00006909 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00006910 else
6911 return BranchWritePC((const Context)context, addr);
6912}
6913
Johnny Chen26863dc2011-02-09 23:43:29 +00006914// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
6915bool
Johnny Chen668b4512011-02-15 21:08:58 +00006916EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00006917{
6918 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00006919 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00006920 else
6921 return BranchWritePC((const Context)context, addr);
6922}
6923
Johnny Chenee9b1f72011-02-09 01:00:31 +00006924EmulateInstructionARM::Mode
6925EmulateInstructionARM::CurrentInstrSet ()
6926{
6927 return m_inst_mode;
6928}
6929
6930// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00006931// ReadInstruction() is performed. This function has a side effect of updating
6932// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00006933bool
6934EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
6935{
Johnny Chen558133b2011-02-09 23:59:17 +00006936 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006937 switch (arm_or_thumb)
6938 {
6939 default:
6940 return false;
6941 eModeARM:
6942 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006943 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006944 break;
6945 eModeThumb:
6946 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006947 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006948 break;
6949 }
6950 return true;
6951}
6952
Johnny Chenef21b592011-02-10 01:52:38 +00006953// This function returns TRUE if the processor currently provides support for
6954// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
6955// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
6956bool
6957EmulateInstructionARM::UnalignedSupport()
6958{
6959 return (ArchVersion() >= ARMv7);
6960}
6961
Johnny Chenbf6ad172011-02-11 01:29:53 +00006962// The main addition and subtraction instructions can produce status information
6963// about both unsigned carry and signed overflow conditions. This status
6964// information can be used to synthesize multi-word additions and subtractions.
6965EmulateInstructionARM::AddWithCarryResult
6966EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
6967{
6968 uint32_t result;
6969 uint8_t carry_out;
6970 uint8_t overflow;
6971
6972 uint64_t unsigned_sum = x + y + carry_in;
6973 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
6974
6975 result = UnsignedBits(unsigned_sum, 31, 0);
6976 carry_out = (result == unsigned_sum ? 0 : 1);
6977 overflow = ((int32_t)result == signed_sum ? 0 : 1);
6978
6979 AddWithCarryResult res = { result, carry_out, overflow };
6980 return res;
6981}
6982
Johnny Chen157b9592011-02-18 21:13:05 +00006983uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00006984EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00006985{
Johnny Chene39f22d2011-02-19 01:36:13 +00006986 uint32_t reg_kind, reg_num;
6987 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00006988 {
Johnny Chene39f22d2011-02-19 01:36:13 +00006989 case SP_REG:
6990 reg_kind = eRegisterKindGeneric;
6991 reg_num = LLDB_REGNUM_GENERIC_SP;
6992 break;
6993 case LR_REG:
6994 reg_kind = eRegisterKindGeneric;
6995 reg_num = LLDB_REGNUM_GENERIC_RA;
6996 break;
6997 case PC_REG:
6998 reg_kind = eRegisterKindGeneric;
6999 reg_num = LLDB_REGNUM_GENERIC_PC;
7000 break;
7001 default:
7002 if (0 <= num && num < SP_REG)
7003 {
7004 reg_kind = eRegisterKindDWARF;
7005 reg_num = dwarf_r0 + num;
7006 }
Johnny Chen157b9592011-02-18 21:13:05 +00007007 else
Johnny Chene39f22d2011-02-19 01:36:13 +00007008 {
7009 assert(0 && "Invalid register number");
7010 *success = false;
7011 return ~0u;
7012 }
7013 break;
Johnny Chen157b9592011-02-18 21:13:05 +00007014 }
Johnny Chene39f22d2011-02-19 01:36:13 +00007015
7016 // Read our register.
7017 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
7018
7019 // When executing an ARM instruction , PC reads as the address of the current
7020 // instruction plus 8.
7021 // When executing a Thumb instruction , PC reads as the address of the current
7022 // instruction plus 4.
7023 if (num == 15)
7024 {
7025 if (CurrentInstrSet() == eModeARM)
7026 val += 8;
7027 else
7028 val += 4;
7029 }
Johnny Chen157b9592011-02-18 21:13:05 +00007030
7031 return val;
7032}
7033
Johnny Chenca67d1c2011-02-17 01:35:27 +00007034// Write the result to the ARM core register Rd, and optionally update the
7035// condition flags based on the result.
7036//
7037// This helper method tries to encapsulate the following pseudocode from the
7038// ARM Architecture Reference Manual:
7039//
7040// if d == 15 then // Can only occur for encoding A1
7041// ALUWritePC(result); // setflags is always FALSE here
7042// else
7043// R[d] = result;
7044// if setflags then
7045// APSR.N = result<31>;
7046// APSR.Z = IsZeroBit(result);
7047// APSR.C = carry;
7048// // APSR.V unchanged
7049//
7050// In the above case, the API client does not pass in the overflow arg, which
7051// defaults to ~0u.
7052bool
Johnny Chen10530c22011-02-17 22:37:12 +00007053EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
7054 const uint32_t result,
7055 const uint32_t Rd,
7056 bool setflags,
7057 const uint32_t carry,
7058 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00007059{
7060 if (Rd == 15)
7061 {
7062 if (!ALUWritePC (context, result))
7063 return false;
7064 }
7065 else
7066 {
7067 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
7068 return false;
7069 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00007070 return WriteFlags (context, result, carry, overflow);
7071 }
7072 return true;
7073}
7074
7075// This helper method tries to encapsulate the following pseudocode from the
7076// ARM Architecture Reference Manual:
7077//
7078// APSR.N = result<31>;
7079// APSR.Z = IsZeroBit(result);
7080// APSR.C = carry;
7081// APSR.V = overflow
7082//
7083// Default arguments can be specified for carry and overflow parameters, which means
7084// not to update the respective flags.
7085bool
7086EmulateInstructionARM::WriteFlags (Context &context,
7087 const uint32_t result,
7088 const uint32_t carry,
7089 const uint32_t overflow)
7090{
7091 m_new_inst_cpsr = m_inst_cpsr;
7092 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
7093 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
7094 if (carry != ~0u)
7095 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
7096 if (overflow != ~0u)
7097 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
7098 if (m_new_inst_cpsr != m_inst_cpsr)
7099 {
7100 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
7101 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00007102 }
7103 return true;
7104}
7105
Greg Clayton64c84432011-01-21 22:02:52 +00007106bool
7107EmulateInstructionARM::EvaluateInstruction ()
7108{
Johnny Chenc315f862011-02-05 00:46:10 +00007109 // Advance the ITSTATE bits to their values for the next instruction.
7110 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
7111 m_it_session.ITAdvance();
7112
Greg Clayton64c84432011-01-21 22:02:52 +00007113 return false;
7114}