blob: 2df182bcbc52f7bd45d0e1122aa7115288030765 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
132#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000133
Johnny Chen0e00af22011-02-10 19:40:42 +0000134//----------------------------------------------------------------------
135//
136// EmulateInstructionARM implementation
137//
138//----------------------------------------------------------------------
139
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140void
141EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145void
146EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000147{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000148}
149
Caroline Ticefa172202011-02-11 22:49:54 +0000150// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
151bool
152EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
153{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000154 EmulateInstruction::Context context;
155 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
156 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000157
158 uint32_t random_data = rand ();
159 const uint32_t addr_byte_size = GetAddressByteSize();
160
Caroline Ticecc96eb52011-02-17 19:20:40 +0000161 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000162 return false;
163
164 return true;
165}
166
Caroline Tice713c2662011-02-11 17:59:55 +0000167// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
168bool
169EmulateInstructionARM::WriteBits32Unknown (int n)
170{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000171 EmulateInstruction::Context context;
172 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
173 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000174
Johnny Chen62ff6f52011-02-11 18:11:22 +0000175 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
177
178 if (!success)
179 return false;
180
181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
182 return false;
183
184 return true;
185}
186
Johnny Chen08c25e82011-01-31 18:02:28 +0000187// Push Multiple Registers stores multiple registers to the stack, storing to
188// consecutive memory locations ending just below the address in SP, and updates
189// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000190bool
Johnny Chen9f687722011-02-18 00:02:28 +0000191EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000192{
193#if 0
194 // ARM pseudo code...
195 if (ConditionPassed())
196 {
197 EncodingSpecificOperations();
198 NullCheckIfThumbEE(13);
199 address = SP - 4*BitCount(registers);
200
201 for (i = 0 to 14)
202 {
203 if (registers<i> == ’1’)
204 {
205 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
206 MemA[address,4] = bits(32) UNKNOWN;
207 else
208 MemA[address,4] = R[i];
209 address = address + 4;
210 }
211 }
212
213 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
214 MemA[address,4] = PCStoreValue();
215
216 SP = SP - 4*BitCount(registers);
217 }
218#endif
219
220 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000222 if (!success)
223 return false;
224
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000228 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000232 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000235 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000237 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000238 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000239 // if BitCount(registers) < 1 then UNPREDICTABLE;
240 if (BitCount(registers) < 1)
241 return false;
242 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 case eEncodingT2:
244 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000245 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000246 // if BitCount(registers) < 2 then UNPREDICTABLE;
247 if (BitCount(registers) < 2)
248 return false;
249 break;
250 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000251 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000257 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000258 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000259 // Instead of return false, let's handle the following case as well,
260 // which amounts to pushing one reg onto the full descending stacks.
261 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000262 break;
263 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000264 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000265 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000270 default:
271 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000272 }
Johnny Chence1ca772011-01-25 01:13:00 +0000273 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000274 addr_t addr = sp - sp_offset;
275 uint32_t i;
276
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000277 EmulateInstruction::Context context;
278 context.type = EmulateInstruction::eContextPushRegisterOnStack;
279 Register dwarf_reg;
280 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000281 for (i=0; i<15; ++i)
282 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000283 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000285 dwarf_reg.num = dwarf_r0 + i;
286 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000290 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000291 return false;
292 addr += addr_byte_size;
293 }
294 }
295
Johnny Chen7c1bf922011-02-08 23:49:37 +0000296 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000297 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000298 dwarf_reg.num = dwarf_pc;
299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000300 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000301 if (!success)
302 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000303 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000304 return false;
305 }
306
307 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000308 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000309
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000311 return false;
312 }
313 return true;
314}
315
Johnny Chenef85e912011-01-31 23:07:40 +0000316// Pop Multiple Registers loads multiple registers from the stack, loading from
317// consecutive memory locations staring at the address in SP, and updates
318// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319bool
Johnny Chen9f687722011-02-18 00:02:28 +0000320EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000321{
322#if 0
323 // ARM pseudo code...
324 if (ConditionPassed())
325 {
326 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
327 address = SP;
328 for i = 0 to 14
329 if registers<i> == ‘1’ then
330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
331 if registers<15> == ‘1’ then
332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
336 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
337 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
338 }
339#endif
340
341 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000343 if (!success)
344 return false;
345
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000347 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000349 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000350 if (!success)
351 return false;
352 uint32_t registers = 0;
353 uint32_t Rt; // the destination register
354 switch (encoding) {
355 case eEncodingT1:
356 registers = Bits32(opcode, 7, 0);
357 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000358 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000359 registers |= (1u << 15);
360 // if BitCount(registers) < 1 then UNPREDICTABLE;
361 if (BitCount(registers) < 1)
362 return false;
363 break;
364 case eEncodingT2:
365 // Ignore bit 13.
366 registers = Bits32(opcode, 15, 0) & ~0x2000;
367 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000368 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000370 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
371 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
372 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000373 break;
374 case eEncodingT3:
375 Rt = Bits32(opcode, 15, 12);
376 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000377 if (Rt == 13)
378 return false;
379 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000380 return false;
381 registers = (1u << Rt);
382 break;
383 case eEncodingA1:
384 registers = Bits32(opcode, 15, 0);
385 // Instead of return false, let's handle the following case as well,
386 // which amounts to popping one reg from the full descending stacks.
387 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
388
389 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000390 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000391 return false;
392 break;
393 case eEncodingA2:
394 Rt = Bits32(opcode, 15, 12);
395 // if t == 13 then UNPREDICTABLE;
396 if (Rt == dwarf_sp)
397 return false;
398 registers = (1u << Rt);
399 break;
400 default:
401 return false;
402 }
403 addr_t sp_offset = addr_byte_size * BitCount (registers);
404 addr_t addr = sp;
405 uint32_t i, data;
406
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000407 EmulateInstruction::Context context;
408 context.type = EmulateInstruction::eContextPopRegisterOffStack;
409 Register dwarf_reg;
410 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000411 for (i=0; i<15; ++i)
412 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000413 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 dwarf_reg.num = dwarf_r0 + i;
416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000417 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000418 if (!success)
419 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 return false;
422 addr += addr_byte_size;
423 }
424 }
425
Johnny Chen7c1bf922011-02-08 23:49:37 +0000426 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000428 dwarf_reg.num = dwarf_pc;
429 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000430 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000431 if (!success)
432 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000433 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000434 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 addr += addr_byte_size;
437 }
438
439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000440 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000441
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 }
445 return true;
446}
447
Johnny Chen5b442b72011-01-27 19:34:30 +0000448// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000450bool
Johnny Chen9f687722011-02-18 00:02:28 +0000451EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000452{
453#if 0
454 // ARM pseudo code...
455 if (ConditionPassed())
456 {
457 EncodingSpecificOperations();
458 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
459 if d == 15 then
460 ALUWritePC(result); // setflags is always FALSE here
461 else
462 R[d] = result;
463 if setflags then
464 APSR.N = result<31>;
465 APSR.Z = IsZeroBit(result);
466 APSR.C = carry;
467 APSR.V = overflow;
468 }
469#endif
470
471 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 if (!success)
474 return false;
475
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000478 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481 uint32_t Rd; // the destination register
482 uint32_t imm32;
483 switch (encoding) {
484 case eEncodingT1:
485 Rd = 7;
486 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
487 break;
488 case eEncodingA1:
489 Rd = Bits32(opcode, 15, 12);
490 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
491 break;
492 default:
493 return false;
494 }
495 addr_t sp_offset = imm32;
496 addr_t addr = sp + sp_offset; // a pointer to the stack area
497
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000498 EmulateInstruction::Context context;
499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
500 Register sp_reg;
501 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
502 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000505 return false;
506 }
507 return true;
508}
509
Johnny Chen2ccad832011-01-28 19:57:25 +0000510// Set r7 or ip to the current stack pointer.
511// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000512bool
Johnny Chen9f687722011-02-18 00:02:28 +0000513EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000514{
515#if 0
516 // ARM pseudo code...
517 if (ConditionPassed())
518 {
519 EncodingSpecificOperations();
520 result = R[m];
521 if d == 15 then
522 ALUWritePC(result); // setflags is always FALSE here
523 else
524 R[d] = result;
525 if setflags then
526 APSR.N = result<31>;
527 APSR.Z = IsZeroBit(result);
528 // APSR.C unchanged
529 // APSR.V unchanged
530 }
531#endif
532
533 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000535 //if (!success)
536 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000537
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000540 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000541 if (!success)
542 return false;
543 uint32_t Rd; // the destination register
544 switch (encoding) {
545 case eEncodingT1:
546 Rd = 7;
547 break;
548 case eEncodingA1:
549 Rd = 12;
550 break;
551 default:
552 return false;
553 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000554
555 EmulateInstruction::Context context;
556 context.type = EmulateInstruction::eContextRegisterPlusOffset;
557 Register sp_reg;
558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
559 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000560
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000562 return false;
563 }
564 return true;
565}
566
Johnny Chen1c13b622011-01-29 00:11:15 +0000567// Move from high register (r8-r15) to low register (r0-r7).
568// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569bool
Johnny Chen9f687722011-02-18 00:02:28 +0000570EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000571{
Johnny Chen9f687722011-02-18 00:02:28 +0000572 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000573}
574
575// Move from register to register.
576// MOV (register)
577bool
Johnny Chen9f687722011-02-18 00:02:28 +0000578EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000579{
Johnny Chen1c13b622011-01-29 00:11:15 +0000580#if 0
581 // ARM pseudo code...
582 if (ConditionPassed())
583 {
584 EncodingSpecificOperations();
585 result = R[m];
586 if d == 15 then
587 ALUWritePC(result); // setflags is always FALSE here
588 else
589 R[d] = result;
590 if setflags then
591 APSR.N = result<31>;
592 APSR.Z = IsZeroBit(result);
593 // APSR.C unchanged
594 // APSR.V unchanged
595 }
596#endif
597
598 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 if (!success)
601 return false;
602
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000603 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 {
605 uint32_t Rm; // the source register
606 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000607 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000608 switch (encoding) {
609 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000610 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000612 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000613 if (Rd == 15 && InITBlock() && !LastInITBlock())
614 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000615 break;
616 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000617 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000620 if (InITBlock())
621 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000622 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 case eEncodingT3:
624 Rd = Bits32(opcode, 11, 8);
625 Rm = Bits32(opcode, 3, 0);
626 setflags = BitIsSet(opcode, 20);
627 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
628 if (setflags && (BadReg(Rd) || BadReg(Rm)))
629 return false;
630 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
631 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
632 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000633 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000634 default:
635 return false;
636 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000637 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000638 if (!success)
639 return false;
640
641 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000642 EmulateInstruction::Context context;
643 context.type = EmulateInstruction::eContextRegisterPlusOffset;
644 Register dwarf_reg;
645 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
646 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000647
Johnny Chen10530c22011-02-17 22:37:12 +0000648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000649 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
Johnny Chen9f687722011-02-18 00:02:28 +0000658EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
677 bool success = false;
678 const uint32_t opcode = OpcodeAsUnsigned (&success);
679 if (!success)
680 return false;
681
682 if (ConditionPassed())
683 {
684 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000685 uint32_t imm32; // the immediate value to be written to Rd
686 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
687 bool setflags;
688 switch (encoding) {
689 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000690 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000691 setflags = !InITBlock();
692 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000693 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000694 break;
695 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000696 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000697 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000698 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000699 if (BadReg(Rd))
700 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000701 break;
702 default:
703 return false;
704 }
705 uint32_t result = imm32;
706
707 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000708 EmulateInstruction::Context context;
709 context.type = EmulateInstruction::eContextImmediate;
710 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000711
Johnny Chen10530c22011-02-17 22:37:12 +0000712 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000713 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000714 }
715 return true;
716}
717
Johnny Chend642a6a2011-02-22 01:01:03 +0000718// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
719// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000720bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000721EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000722{
723#if 0
724 // ARM pseudo code...
725 if (ConditionPassed())
726 {
727 EncodingSpecificOperations();
728 result = NOT(imm32);
729 if d == 15 then // Can only occur for ARM encoding
730 ALUWritePC(result); // setflags is always FALSE here
731 else
732 R[d] = result;
733 if setflags then
734 APSR.N = result<31>;
735 APSR.Z = IsZeroBit(result);
736 APSR.C = carry;
737 // APSR.V unchanged
738 }
739#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000740 bool success = false;
741 const uint32_t opcode = OpcodeAsUnsigned (&success);
742 if (!success)
743 return false;
744
745 if (ConditionPassed())
746 {
747 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000748 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
749 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000750 bool setflags;
751 switch (encoding) {
752 case eEncodingT1:
753 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000754 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000755 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000756 break;
757 case eEncodingA1:
758 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000759 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000760 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
761 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
762 // TODO: Emulate SUBS PC, LR and related instructions.
763 if (Rd == 15 && setflags)
764 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 break;
766 default:
767 return false;
768 }
769 uint32_t result = ~imm32;
770
771 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000772 EmulateInstruction::Context context;
773 context.type = EmulateInstruction::eContextImmediate;
774 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000775
Johnny Chen10530c22011-02-17 22:37:12 +0000776 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000777 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000778 }
779 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000780}
781
Johnny Chend642a6a2011-02-22 01:01:03 +0000782// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
783// It can optionally update the condition flags based on the result.
784bool
785EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
786{
787#if 0
788 // ARM pseudo code...
789 if (ConditionPassed())
790 {
791 EncodingSpecificOperations();
792 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
793 result = NOT(shifted);
794 if d == 15 then // Can only occur for ARM encoding
795 ALUWritePC(result); // setflags is always FALSE here
796 else
797 R[d] = result;
798 if setflags then
799 APSR.N = result<31>;
800 APSR.Z = IsZeroBit(result);
801 APSR.C = carry;
802 // APSR.V unchanged
803 }
804#endif
805
806 bool success = false;
807 const uint32_t opcode = OpcodeAsUnsigned (&success);
808 if (!success)
809 return false;
810
811 if (ConditionPassed())
812 {
813 uint32_t Rm; // the source register
814 uint32_t Rd; // the destination register
815 ARM_ShifterType shift_t;
816 uint32_t shift_n; // the shift applied to the value read from Rm
817 bool setflags;
818 uint32_t carry; // the carry bit after the shift operation
819 switch (encoding) {
820 case eEncodingT1:
821 Rd = Bits32(opcode, 2, 0);
822 Rm = Bits32(opcode, 5, 3);
823 setflags = !InITBlock();
824 shift_t = SRType_LSL;
825 shift_n = 0;
826 if (InITBlock())
827 return false;
828 break;
829 case eEncodingT2:
830 Rd = Bits32(opcode, 11, 8);
831 Rm = Bits32(opcode, 3, 0);
832 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000833 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000834 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000835 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000836 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000837 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000838 case eEncodingA1:
839 Rd = Bits32(opcode, 15, 12);
840 Rm = Bits32(opcode, 3, 0);
841 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000842 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000843 break;
844 default:
845 return false;
846 }
847 uint32_t value = ReadCoreReg(Rm, &success);
848 if (!success)
849 return false;
850
851 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
852 uint32_t result = ~shifted;
853
854 // The context specifies that an immediate is to be moved into Rd.
855 EmulateInstruction::Context context;
856 context.type = EmulateInstruction::eContextImmediate;
857 context.SetNoArgs ();
858
859 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
860 return false;
861 }
862 return true;
863}
864
Johnny Chen788e0552011-01-27 22:52:23 +0000865// PC relative immediate load into register, possibly followed by ADD (SP plus register).
866// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000867bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000868EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000869{
870#if 0
871 // ARM pseudo code...
872 if (ConditionPassed())
873 {
874 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
875 base = Align(PC,4);
876 address = if add then (base + imm32) else (base - imm32);
877 data = MemU[address,4];
878 if t == 15 then
879 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
880 elsif UnalignedSupport() || address<1:0> = ‘00’ then
881 R[t] = data;
882 else // Can only apply before ARMv7
883 if CurrentInstrSet() == InstrSet_ARM then
884 R[t] = ROR(data, 8*UInt(address<1:0>));
885 else
886 R[t] = bits(32) UNKNOWN;
887 }
888#endif
889
890 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000891 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000892 if (!success)
893 return false;
894
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000895 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000896 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000897 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000898 if (!success)
899 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000900
901 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000902 EmulateInstruction::Context context;
903 context.type = EmulateInstruction::eContextRegisterPlusOffset;
904 Register pc_reg;
905 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
906 context.SetRegisterPlusOffset (pc_reg, 0);
907
Johnny Chenc9de9102011-02-11 19:12:30 +0000908 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000909 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000910 bool add; // +imm32 or -imm32?
911 addr_t base; // the base address
912 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000913 uint32_t data; // the literal data value from the PC relative load
914 switch (encoding) {
915 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000916 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000917 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000918 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000919 break;
920 case eEncodingT2:
921 Rt = Bits32(opcode, 15, 12);
922 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
923 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000924 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000925 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000926 break;
927 default:
928 return false;
929 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000930
Johnny Chene39f22d2011-02-19 01:36:13 +0000931 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000932 if (add)
933 address = base + imm32;
934 else
935 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000936
937 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000938 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000939 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000940 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000941
942 if (Rt == 15)
943 {
944 if (Bits32(address, 1, 0) == 0)
945 {
946 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000947 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000948 return false;
949 }
950 else
951 return false;
952 }
953 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
954 {
955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
956 return false;
957 }
958 else // We don't handle ARM for now.
959 return false;
960
961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000962 return false;
963 }
964 return true;
965}
966
Johnny Chen5b442b72011-01-27 19:34:30 +0000967// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000968// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000969bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000970EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000971{
972#if 0
973 // ARM pseudo code...
974 if (ConditionPassed())
975 {
976 EncodingSpecificOperations();
977 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
978 if d == 15 then // Can only occur for ARM encoding
979 ALUWritePC(result); // setflags is always FALSE here
980 else
981 R[d] = result;
982 if setflags then
983 APSR.N = result<31>;
984 APSR.Z = IsZeroBit(result);
985 APSR.C = carry;
986 APSR.V = overflow;
987 }
988#endif
989
990 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000991 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000992 if (!success)
993 return false;
994
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000995 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000996 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000997 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000998 if (!success)
999 return false;
1000 uint32_t imm32; // the immediate operand
1001 switch (encoding) {
1002 case eEncodingT2:
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 Chenc9e747f2011-02-23 01:55:07 +00001410// This instruction subtracts an immediate value from the SP value, and writes
1411// the result to the destination register.
1412//
1413// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001414bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001415EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416{
1417#if 0
1418 // ARM pseudo code...
1419 if (ConditionPassed())
1420 {
1421 EncodingSpecificOperations();
1422 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1423 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001424 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001425 else
1426 R[d] = result;
1427 if setflags then
1428 APSR.N = result<31>;
1429 APSR.Z = IsZeroBit(result);
1430 APSR.C = carry;
1431 APSR.V = overflow;
1432 }
1433#endif
1434
1435 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001436 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001437 if (!success)
1438 return false;
1439
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001440 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001441 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001442 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001443 if (!success)
1444 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001445
1446 uint32_t Rd;
1447 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001448 uint32_t imm32;
1449 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001450 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001451 Rd = 13;
1452 setflags = false;
Johnny Chene4455022011-01-26 00:08:59 +00001453 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001454 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001455 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001456 Rd = Bits32(opcode, 11, 8);
1457 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001458 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001459 if (Rd == 15 && setflags)
1460 return EmulateCMPImm(eEncodingT2);
1461 if (Rd == 15 && !setflags)
1462 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001463 break;
1464 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001465 Rd = Bits32(opcode, 11, 8);
1466 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001467 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1468 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001469 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001470 Rd = Bits32(opcode, 15, 12);
1471 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001472 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001473 break;
1474 default:
1475 return false;
1476 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001477 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1478
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001479 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001480 if (Rd == 13)
1481 {
1482 context.type = EmulateInstruction::eContextAdjustStackPointer;
1483 context.SetImmediateSigned (-imm32); // the stack pointer offset
1484 }
1485 else
1486 {
1487 context.type = EmulateInstruction::eContextImmediate;
1488 context.SetNoArgs ();
1489 }
1490
1491 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001492 return false;
1493 }
1494 return true;
1495}
1496
Johnny Chen08c25e82011-01-31 18:02:28 +00001497// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001498bool
1499EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001500{
1501#if 0
1502 // ARM pseudo code...
1503 if (ConditionPassed())
1504 {
1505 EncodingSpecificOperations();
1506 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1507 address = if index then offset_addr else R[n];
1508 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1509 if wback then R[n] = offset_addr;
1510 }
1511#endif
1512
1513 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001514 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001515 if (!success)
1516 return false;
1517
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001518 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001519 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001520 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001521 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001522 if (!success)
1523 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001524 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001525 uint32_t imm12;
1526 switch (encoding) {
1527 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001528 Rt = Bits32(opcode, 15, 12);
1529 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001530 break;
1531 default:
1532 return false;
1533 }
1534 addr_t sp_offset = imm12;
1535 addr_t addr = sp - sp_offset;
1536
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001537 EmulateInstruction::Context context;
1538 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1539 Register dwarf_reg;
1540 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001541 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001542 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001543 dwarf_reg.num = dwarf_r0 + Rt;
1544 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001545 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001546 if (!success)
1547 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001548 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001549 return false;
1550 }
1551 else
1552 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001553 dwarf_reg.num = dwarf_pc;
1554 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001555 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001556 if (!success)
1557 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001558 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001559 return false;
1560 }
1561
1562 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001563 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001564
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001565 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001566 return false;
1567 }
1568 return true;
1569}
1570
Johnny Chen08c25e82011-01-31 18:02:28 +00001571// Vector Push stores multiple extension registers to the stack.
1572// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001573bool
1574EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001575{
1576#if 0
1577 // ARM pseudo code...
1578 if (ConditionPassed())
1579 {
1580 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1581 address = SP - imm32;
1582 SP = SP - imm32;
1583 if single_regs then
1584 for r = 0 to regs-1
1585 MemA[address,4] = S[d+r]; address = address+4;
1586 else
1587 for r = 0 to regs-1
1588 // Store as two word-aligned words in the correct order for current endianness.
1589 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1590 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1591 address = address+8;
1592 }
1593#endif
1594
1595 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001596 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001597 if (!success)
1598 return false;
1599
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001600 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001601 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001602 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001603 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001604 if (!success)
1605 return false;
1606 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001607 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001608 uint32_t imm32; // stack offset
1609 uint32_t regs; // number of registers
1610 switch (encoding) {
1611 case eEncodingT1:
1612 case eEncodingA1:
1613 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001614 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001615 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1616 // If UInt(imm8) is odd, see "FSTMX".
1617 regs = Bits32(opcode, 7, 0) / 2;
1618 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1619 if (regs == 0 || regs > 16 || (d + regs) > 32)
1620 return false;
1621 break;
1622 case eEncodingT2:
1623 case eEncodingA2:
1624 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001625 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001626 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1627 regs = Bits32(opcode, 7, 0);
1628 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1629 if (regs == 0 || regs > 16 || (d + regs) > 32)
1630 return false;
1631 break;
1632 default:
1633 return false;
1634 }
1635 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1636 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1637 addr_t sp_offset = imm32;
1638 addr_t addr = sp - sp_offset;
1639 uint32_t i;
1640
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001641 EmulateInstruction::Context context;
1642 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1643 Register dwarf_reg;
1644 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001645 for (i=d; i<regs; ++i)
1646 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001647 dwarf_reg.num = start_reg + i;
1648 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001649 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001650 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001651 if (!success)
1652 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001653 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001654 return false;
1655 addr += reg_byte_size;
1656 }
1657
1658 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001659 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001660
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001661 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001662 return false;
1663 }
1664 return true;
1665}
1666
Johnny Chen587a0a42011-02-01 18:35:28 +00001667// Vector Pop loads multiple extension registers from the stack.
1668// It also updates SP to point just above the loaded data.
1669bool
1670EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1671{
1672#if 0
1673 // ARM pseudo code...
1674 if (ConditionPassed())
1675 {
1676 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1677 address = SP;
1678 SP = SP + imm32;
1679 if single_regs then
1680 for r = 0 to regs-1
1681 S[d+r] = MemA[address,4]; address = address+4;
1682 else
1683 for r = 0 to regs-1
1684 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1685 // Combine the word-aligned words in the correct order for current endianness.
1686 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1687 }
1688#endif
1689
1690 bool success = false;
1691 const uint32_t opcode = OpcodeAsUnsigned (&success);
1692 if (!success)
1693 return false;
1694
1695 if (ConditionPassed())
1696 {
1697 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001698 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001699 if (!success)
1700 return false;
1701 bool single_regs;
1702 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1703 uint32_t imm32; // stack offset
1704 uint32_t regs; // number of registers
1705 switch (encoding) {
1706 case eEncodingT1:
1707 case eEncodingA1:
1708 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001709 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001710 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1711 // If UInt(imm8) is odd, see "FLDMX".
1712 regs = Bits32(opcode, 7, 0) / 2;
1713 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1714 if (regs == 0 || regs > 16 || (d + regs) > 32)
1715 return false;
1716 break;
1717 case eEncodingT2:
1718 case eEncodingA2:
1719 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001720 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001721 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1722 regs = Bits32(opcode, 7, 0);
1723 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1724 if (regs == 0 || regs > 16 || (d + regs) > 32)
1725 return false;
1726 break;
1727 default:
1728 return false;
1729 }
1730 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1731 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1732 addr_t sp_offset = imm32;
1733 addr_t addr = sp;
1734 uint32_t i;
1735 uint64_t data; // uint64_t to accomodate 64-bit registers.
1736
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001737 EmulateInstruction::Context context;
1738 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1739 Register dwarf_reg;
1740 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001741 for (i=d; i<regs; ++i)
1742 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001743 dwarf_reg.num = start_reg + i;
1744 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001745 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001746 if (!success)
1747 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001748 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001749 return false;
1750 addr += reg_byte_size;
1751 }
1752
1753 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001754 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001755
1756 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1757 return false;
1758 }
1759 return true;
1760}
1761
Johnny Chenb77be412011-02-04 00:40:18 +00001762// SVC (previously SWI)
1763bool
1764EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1765{
1766#if 0
1767 // ARM pseudo code...
1768 if (ConditionPassed())
1769 {
1770 EncodingSpecificOperations();
1771 CallSupervisor();
1772 }
1773#endif
1774
1775 bool success = false;
1776 const uint32_t opcode = OpcodeAsUnsigned (&success);
1777 if (!success)
1778 return false;
1779
1780 if (ConditionPassed())
1781 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001782 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001783 addr_t lr; // next instruction address
1784 if (!success)
1785 return false;
1786 uint32_t imm32; // the immediate constant
1787 uint32_t mode; // ARM or Thumb mode
1788 switch (encoding) {
1789 case eEncodingT1:
1790 lr = (pc + 2) | 1u; // return address
1791 imm32 = Bits32(opcode, 7, 0);
1792 mode = eModeThumb;
1793 break;
1794 case eEncodingA1:
1795 lr = pc + 4; // return address
1796 imm32 = Bits32(opcode, 23, 0);
1797 mode = eModeARM;
1798 break;
1799 default:
1800 return false;
1801 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001802
1803 EmulateInstruction::Context context;
1804 context.type = EmulateInstruction::eContextSupervisorCall;
1805 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001806 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1807 return false;
1808 }
1809 return true;
1810}
1811
Johnny Chenc315f862011-02-05 00:46:10 +00001812// If Then makes up to four following instructions (the IT block) conditional.
1813bool
1814EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1815{
1816#if 0
1817 // ARM pseudo code...
1818 EncodingSpecificOperations();
1819 ITSTATE.IT<7:0> = firstcond:mask;
1820#endif
1821
1822 bool success = false;
1823 const uint32_t opcode = OpcodeAsUnsigned (&success);
1824 if (!success)
1825 return false;
1826
1827 m_it_session.InitIT(Bits32(opcode, 7, 0));
1828 return true;
1829}
1830
Johnny Chen3b620b32011-02-07 20:11:47 +00001831// Branch causes a branch to a target address.
1832bool
1833EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1834{
1835#if 0
1836 // ARM pseudo code...
1837 if (ConditionPassed())
1838 {
1839 EncodingSpecificOperations();
1840 BranchWritePC(PC + imm32);
1841 }
1842#endif
1843
1844 bool success = false;
1845 const uint32_t opcode = OpcodeAsUnsigned (&success);
1846 if (!success)
1847 return false;
1848
Johnny Chen9ee056b2011-02-08 00:06:35 +00001849 if (ConditionPassed())
1850 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001851 EmulateInstruction::Context context;
1852 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001853 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001854 if (!success)
1855 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001856 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001857 int32_t imm32; // PC-relative offset
1858 switch (encoding) {
1859 case eEncodingT1:
1860 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1861 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001862 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001863 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001864 break;
1865 case eEncodingT2:
1866 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001867 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001868 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001869 break;
1870 case eEncodingT3:
1871 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1872 {
Johnny Chenbd599902011-02-10 21:39:01 +00001873 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001874 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001875 uint32_t J1 = Bit32(opcode, 13);
1876 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001877 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001878 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001879 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001880 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001881 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001882 break;
1883 }
1884 case eEncodingT4:
1885 {
Johnny Chenbd599902011-02-10 21:39:01 +00001886 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001887 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001888 uint32_t J1 = Bit32(opcode, 13);
1889 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001890 uint32_t imm11 = Bits32(opcode, 10, 0);
1891 uint32_t I1 = !(J1 ^ S);
1892 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001893 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001894 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001895 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001896 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001897 break;
1898 }
1899 case eEncodingA1:
1900 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001901 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001902 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001903 break;
1904 default:
1905 return false;
1906 }
1907 if (!BranchWritePC(context, target))
1908 return false;
1909 }
1910 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001911}
1912
Johnny Chen53ebab72011-02-08 23:21:57 +00001913// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1914// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1915// CBNZ, CBZ
1916bool
1917EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1918{
1919#if 0
1920 // ARM pseudo code...
1921 EncodingSpecificOperations();
1922 if nonzero ^ IsZero(R[n]) then
1923 BranchWritePC(PC + imm32);
1924#endif
1925
1926 bool success = false;
1927 const uint32_t opcode = OpcodeAsUnsigned (&success);
1928 if (!success)
1929 return false;
1930
1931 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00001932 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001933 if (!success)
1934 return false;
1935
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001936 EmulateInstruction::Context context;
1937 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001938 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001939 if (!success)
1940 return false;
1941
1942 addr_t target; // target address
1943 uint32_t imm32; // PC-relative offset to branch forward
1944 bool nonzero;
1945 switch (encoding) {
1946 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001947 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001948 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00001949 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001950 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001951 break;
1952 default:
1953 return false;
1954 }
1955 if (nonzero ^ (reg_val == 0))
1956 if (!BranchWritePC(context, target))
1957 return false;
1958
1959 return true;
1960}
1961
Johnny Chen60299ec2011-02-17 19:34:27 +00001962// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1963// A base register provides a pointer to the table, and a second register supplies an index into the table.
1964// The branch length is twice the value of the byte returned from the table.
1965//
1966// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1967// A base register provides a pointer to the table, and a second register supplies an index into the table.
1968// The branch length is twice the value of the halfword returned from the table.
1969// TBB, TBH
1970bool
1971EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1972{
1973#if 0
1974 // ARM pseudo code...
1975 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1976 if is_tbh then
1977 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1978 else
1979 halfwords = UInt(MemU[R[n]+R[m], 1]);
1980 BranchWritePC(PC + 2*halfwords);
1981#endif
1982
1983 bool success = false;
1984 const uint32_t opcode = OpcodeAsUnsigned (&success);
1985 if (!success)
1986 return false;
1987
1988 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1989 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1990 bool is_tbh; // true if table branch halfword
1991 switch (encoding) {
1992 case eEncodingT1:
1993 Rn = Bits32(opcode, 19, 16);
1994 Rm = Bits32(opcode, 3, 0);
1995 is_tbh = BitIsSet(opcode, 4);
1996 if (Rn == 13 || BadReg(Rm))
1997 return false;
1998 if (InITBlock() && !LastInITBlock())
1999 return false;
2000 break;
2001 default:
2002 return false;
2003 }
2004
2005 // Read the address of the table from the operand register Rn.
2006 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002007 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002008 if (!success)
2009 return false;
2010
2011 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002012 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002013 if (!success)
2014 return false;
2015
2016 // the offsetted table address
2017 addr_t addr = base + (is_tbh ? index*2 : index);
2018
2019 // PC-relative offset to branch forward
2020 EmulateInstruction::Context context;
2021 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002022 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002023 if (!success)
2024 return false;
2025
Johnny Chene39f22d2011-02-19 01:36:13 +00002026 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002027 if (!success)
2028 return false;
2029
2030 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002031 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002032 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2033 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2034
2035 if (!BranchWritePC(context, target))
2036 return false;
2037
2038 return true;
2039}
2040
Johnny Chen8fa20592011-02-18 01:22:22 +00002041// This instruction adds an immediate value to a register value, and writes the result to the destination
2042// register. It can optionally update the condition flags based on the result.
2043bool
2044EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2045{
2046#if 0
2047 // ARM pseudo code...
2048 if ConditionPassed() then
2049 EncodingSpecificOperations();
2050 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2051 if d == 15 then
2052 ALUWritePC(result); // setflags is always FALSE here
2053 else
2054 R[d] = result;
2055 if setflags then
2056 APSR.N = result<31>;
2057 APSR.Z = IsZeroBit(result);
2058 APSR.C = carry;
2059 APSR.V = overflow;
2060#endif
2061
2062 bool success = false;
2063 const uint32_t opcode = OpcodeAsUnsigned (&success);
2064 if (!success)
2065 return false;
2066
2067 if (ConditionPassed())
2068 {
2069 uint32_t Rd, Rn;
2070 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2071 bool setflags;
2072 switch (encoding)
2073 {
2074 case eEncodingA1:
2075 Rd = Bits32(opcode, 15, 12);
2076 Rn = Bits32(opcode, 19, 16);
2077 setflags = BitIsSet(opcode, 20);
2078 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2079 break;
2080 default:
2081 return false;
2082 }
2083
Johnny Chen8fa20592011-02-18 01:22:22 +00002084 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002085 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002086 if (!success)
2087 return false;
2088
2089 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2090
2091 EmulateInstruction::Context context;
2092 context.type = EmulateInstruction::eContextImmediate;
2093 context.SetNoArgs ();
2094
2095 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2096 return false;
2097 }
2098 return true;
2099}
2100
Johnny Chend761dcf2011-02-17 22:03:29 +00002101// This instruction adds a register value and an optionally-shifted register value, and writes the result
2102// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002103bool
Johnny Chen9f687722011-02-18 00:02:28 +00002104EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002105{
2106#if 0
2107 // ARM pseudo code...
2108 if ConditionPassed() then
2109 EncodingSpecificOperations();
2110 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2111 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2112 if d == 15 then
2113 ALUWritePC(result); // setflags is always FALSE here
2114 else
2115 R[d] = result;
2116 if setflags then
2117 APSR.N = result<31>;
2118 APSR.Z = IsZeroBit(result);
2119 APSR.C = carry;
2120 APSR.V = overflow;
2121#endif
2122
2123 bool success = false;
2124 const uint32_t opcode = OpcodeAsUnsigned (&success);
2125 if (!success)
2126 return false;
2127
2128 if (ConditionPassed())
2129 {
2130 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002131 ARM_ShifterType shift_t;
2132 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002133 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002134 switch (encoding)
2135 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002136 case eEncodingT1:
2137 Rd = Bits32(opcode, 2, 0);
2138 Rn = Bits32(opcode, 5, 3);
2139 Rm = Bits32(opcode, 8, 6);
2140 setflags = !InITBlock();
2141 shift_t = SRType_LSL;
2142 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002143 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002144 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002145 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002146 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002147 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002148 shift_t = SRType_LSL;
2149 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002150 if (Rn == 15 && Rm == 15)
2151 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002152 if (Rd == 15 && InITBlock() && !LastInITBlock())
2153 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002154 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002155 case eEncodingA1:
2156 Rd = Bits32(opcode, 15, 12);
2157 Rn = Bits32(opcode, 19, 16);
2158 Rm = Bits32(opcode, 3, 0);
2159 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002160 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002161 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002162 default:
2163 return false;
2164 }
2165
Johnny Chen26863dc2011-02-09 23:43:29 +00002166 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002167 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002168 if (!success)
2169 return false;
2170
2171 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002172 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002173 if (!success)
2174 return false;
2175
Johnny Chene97c0d52011-02-18 19:32:20 +00002176 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002177 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002178
2179 EmulateInstruction::Context context;
2180 context.type = EmulateInstruction::eContextImmediate;
2181 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002182
Johnny Chen10530c22011-02-17 22:37:12 +00002183 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002184 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002185 }
2186 return true;
2187}
2188
Johnny Chen34075cb2011-02-22 01:56:31 +00002189// Compare Negative (immediate) adds a register value and an immediate value.
2190// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002191bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002192EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2193{
2194#if 0
2195 // ARM pseudo code...
2196 if ConditionPassed() then
2197 EncodingSpecificOperations();
2198 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2199 APSR.N = result<31>;
2200 APSR.Z = IsZeroBit(result);
2201 APSR.C = carry;
2202 APSR.V = overflow;
2203#endif
2204
2205 bool success = false;
2206 const uint32_t opcode = OpcodeAsUnsigned (&success);
2207 if (!success)
2208 return false;
2209
2210 uint32_t Rn; // the first operand
2211 uint32_t imm32; // the immediate value to be compared with
2212 switch (encoding) {
2213 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002214 Rn = Bits32(opcode, 19, 16);
2215 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2216 if (Rn == 15)
2217 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002218 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002219 case eEncodingA1:
2220 Rn = Bits32(opcode, 19, 16);
2221 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2222 break;
2223 default:
2224 return false;
2225 }
2226 // Read the register value from the operand register Rn.
2227 uint32_t reg_val = ReadCoreReg(Rn, &success);
2228 if (!success)
2229 return false;
2230
Johnny Chen078fbc62011-02-22 19:48:22 +00002231 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002232
2233 EmulateInstruction::Context context;
2234 context.type = EmulateInstruction::eContextImmediate;
2235 context.SetNoArgs ();
2236 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2237 return false;
2238
2239 return true;
2240}
2241
2242// Compare Negative (register) adds a register value and an optionally-shifted register value.
2243// It updates the condition flags based on the result, and discards the result.
2244bool
2245EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2246{
2247#if 0
2248 // ARM pseudo code...
2249 if ConditionPassed() then
2250 EncodingSpecificOperations();
2251 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2252 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2253 APSR.N = result<31>;
2254 APSR.Z = IsZeroBit(result);
2255 APSR.C = carry;
2256 APSR.V = overflow;
2257#endif
2258
2259 bool success = false;
2260 const uint32_t opcode = OpcodeAsUnsigned (&success);
2261 if (!success)
2262 return false;
2263
2264 uint32_t Rn; // the first operand
2265 uint32_t Rm; // the second operand
2266 ARM_ShifterType shift_t;
2267 uint32_t shift_n; // the shift applied to the value read from Rm
2268 switch (encoding) {
2269 case eEncodingT1:
2270 Rn = Bits32(opcode, 2, 0);
2271 Rm = Bits32(opcode, 5, 3);
2272 shift_t = SRType_LSL;
2273 shift_n = 0;
2274 break;
2275 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002276 Rn = Bits32(opcode, 19, 16);
2277 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002278 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002279 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2280 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002281 return false;
2282 break;
2283 case eEncodingA1:
2284 Rn = Bits32(opcode, 19, 16);
2285 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002286 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002287 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002288 default:
2289 return false;
2290 }
2291 // Read the register value from register Rn.
2292 uint32_t val1 = ReadCoreReg(Rn, &success);
2293 if (!success)
2294 return false;
2295
2296 // Read the register value from register Rm.
2297 uint32_t val2 = ReadCoreReg(Rm, &success);
2298 if (!success)
2299 return false;
2300
2301 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002302 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002303
2304 EmulateInstruction::Context context;
2305 context.type = EmulateInstruction::eContextImmediate;
2306 context.SetNoArgs();
2307 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2308 return false;
2309
2310 return true;
2311}
2312
2313// Compare (immediate) subtracts an immediate value from a register value.
2314// It updates the condition flags based on the result, and discards the result.
2315bool
2316EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002317{
2318#if 0
2319 // ARM pseudo code...
2320 if ConditionPassed() then
2321 EncodingSpecificOperations();
2322 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2323 APSR.N = result<31>;
2324 APSR.Z = IsZeroBit(result);
2325 APSR.C = carry;
2326 APSR.V = overflow;
2327#endif
2328
2329 bool success = false;
2330 const uint32_t opcode = OpcodeAsUnsigned (&success);
2331 if (!success)
2332 return false;
2333
2334 uint32_t Rn; // the first operand
2335 uint32_t imm32; // the immediate value to be compared with
2336 switch (encoding) {
2337 case eEncodingT1:
2338 Rn = Bits32(opcode, 10, 8);
2339 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002340 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002341 case eEncodingT2:
2342 Rn = Bits32(opcode, 19, 16);
2343 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2344 if (Rn == 15)
2345 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002346 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002347 case eEncodingA1:
2348 Rn = Bits32(opcode, 19, 16);
2349 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002350 break;
2351 default:
2352 return false;
2353 }
2354 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002355 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002356 if (!success)
2357 return false;
2358
Johnny Chen10530c22011-02-17 22:37:12 +00002359 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2360
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002361 EmulateInstruction::Context context;
2362 context.type = EmulateInstruction::eContextImmediate;
2363 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002364 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2365 return false;
2366
Johnny Chend4dc4442011-02-11 02:02:56 +00002367 return true;
2368}
2369
Johnny Chen34075cb2011-02-22 01:56:31 +00002370// Compare (register) subtracts an optionally-shifted register value from a register value.
2371// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002372bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002373EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002374{
2375#if 0
2376 // ARM pseudo code...
2377 if ConditionPassed() then
2378 EncodingSpecificOperations();
2379 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2380 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2381 APSR.N = result<31>;
2382 APSR.Z = IsZeroBit(result);
2383 APSR.C = carry;
2384 APSR.V = overflow;
2385#endif
2386
2387 bool success = false;
2388 const uint32_t opcode = OpcodeAsUnsigned (&success);
2389 if (!success)
2390 return false;
2391
2392 uint32_t Rn; // the first operand
2393 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002394 ARM_ShifterType shift_t;
2395 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002396 switch (encoding) {
2397 case eEncodingT1:
2398 Rn = Bits32(opcode, 2, 0);
2399 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002400 shift_t = SRType_LSL;
2401 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002402 break;
2403 case eEncodingT2:
2404 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2405 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002406 shift_t = SRType_LSL;
2407 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002408 if (Rn < 8 && Rm < 8)
2409 return false;
2410 if (Rn == 15 || Rm == 15)
2411 return false;
2412 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002413 case eEncodingA1:
2414 Rn = Bits32(opcode, 19, 16);
2415 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002416 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002417 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002418 default:
2419 return false;
2420 }
2421 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002422 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002423 if (!success)
2424 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002425
Johnny Chene4a4d302011-02-11 21:53:58 +00002426 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002427 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002428 if (!success)
2429 return false;
2430
Johnny Chen34075cb2011-02-22 01:56:31 +00002431 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2432 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002433
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002434 EmulateInstruction::Context context;
2435 context.type = EmulateInstruction::eContextImmediate;
2436 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002437 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2438 return false;
2439
Johnny Chene4a4d302011-02-11 21:53:58 +00002440 return true;
2441}
2442
Johnny Chen82f16aa2011-02-15 20:10:55 +00002443// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2444// shifting in copies of its sign bit, and writes the result to the destination register. It can
2445// optionally update the condition flags based on the result.
2446bool
2447EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2448{
2449#if 0
2450 // ARM pseudo code...
2451 if ConditionPassed() then
2452 EncodingSpecificOperations();
2453 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2454 if d == 15 then // Can only occur for ARM encoding
2455 ALUWritePC(result); // setflags is always FALSE here
2456 else
2457 R[d] = result;
2458 if setflags then
2459 APSR.N = result<31>;
2460 APSR.Z = IsZeroBit(result);
2461 APSR.C = carry;
2462 // APSR.V unchanged
2463#endif
2464
Johnny Chen41a0a152011-02-16 01:27:54 +00002465 return EmulateShiftImm(encoding, SRType_ASR);
2466}
2467
2468// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2469// shifting in copies of its sign bit, and writes the result to the destination register.
2470// The variable number of bits is read from the bottom byte of a register. It can optionally update
2471// the condition flags based on the result.
2472bool
2473EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2474{
2475#if 0
2476 // ARM pseudo code...
2477 if ConditionPassed() then
2478 EncodingSpecificOperations();
2479 shift_n = UInt(R[m]<7:0>);
2480 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
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 EmulateShiftReg(encoding, SRType_ASR);
2490}
2491
2492// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2493// shifting in zeros, and writes the result to the destination register. It can optionally
2494// update the condition flags based on the result.
2495bool
2496EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2497{
2498#if 0
2499 // ARM pseudo code...
2500 if ConditionPassed() then
2501 EncodingSpecificOperations();
2502 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2503 if d == 15 then // Can only occur for ARM encoding
2504 ALUWritePC(result); // setflags is always FALSE here
2505 else
2506 R[d] = result;
2507 if setflags then
2508 APSR.N = result<31>;
2509 APSR.Z = IsZeroBit(result);
2510 APSR.C = carry;
2511 // APSR.V unchanged
2512#endif
2513
2514 return EmulateShiftImm(encoding, SRType_LSL);
2515}
2516
2517// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2518// shifting in zeros, and writes the result to the destination register. The variable number
2519// of bits is read from the bottom byte of a register. It can optionally update the condition
2520// flags based on the result.
2521bool
2522EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2523{
2524#if 0
2525 // ARM pseudo code...
2526 if ConditionPassed() then
2527 EncodingSpecificOperations();
2528 shift_n = UInt(R[m]<7:0>);
2529 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
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 EmulateShiftReg(encoding, SRType_LSL);
2539}
2540
2541// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2542// shifting in zeros, and writes the result to the destination register. It can optionally
2543// update the condition flags based on the result.
2544bool
2545EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2546{
2547#if 0
2548 // ARM pseudo code...
2549 if ConditionPassed() then
2550 EncodingSpecificOperations();
2551 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2552 if d == 15 then // Can only occur for ARM encoding
2553 ALUWritePC(result); // setflags is always FALSE here
2554 else
2555 R[d] = result;
2556 if setflags then
2557 APSR.N = result<31>;
2558 APSR.Z = IsZeroBit(result);
2559 APSR.C = carry;
2560 // APSR.V unchanged
2561#endif
2562
2563 return EmulateShiftImm(encoding, SRType_LSR);
2564}
2565
2566// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2567// shifting in zeros, and writes the result to the destination register. The variable number
2568// of bits is read from the bottom byte of a register. It can optionally update the condition
2569// flags based on the result.
2570bool
2571EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2572{
2573#if 0
2574 // ARM pseudo code...
2575 if ConditionPassed() then
2576 EncodingSpecificOperations();
2577 shift_n = UInt(R[m]<7:0>);
2578 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
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 EmulateShiftReg(encoding, SRType_LSR);
2588}
2589
Johnny Cheneeab4852011-02-16 22:14:44 +00002590// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2591// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2592// It can optionally update the condition flags based on the result.
2593bool
2594EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2595{
2596#if 0
2597 // ARM pseudo code...
2598 if ConditionPassed() then
2599 EncodingSpecificOperations();
2600 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2601 if d == 15 then // Can only occur for ARM encoding
2602 ALUWritePC(result); // setflags is always FALSE here
2603 else
2604 R[d] = result;
2605 if setflags then
2606 APSR.N = result<31>;
2607 APSR.Z = IsZeroBit(result);
2608 APSR.C = carry;
2609 // APSR.V unchanged
2610#endif
2611
2612 return EmulateShiftImm(encoding, SRType_ROR);
2613}
2614
2615// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2616// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2617// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2618// flags based on the result.
2619bool
2620EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2621{
2622#if 0
2623 // ARM pseudo code...
2624 if ConditionPassed() then
2625 EncodingSpecificOperations();
2626 shift_n = UInt(R[m]<7:0>);
2627 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2628 R[d] = result;
2629 if setflags then
2630 APSR.N = result<31>;
2631 APSR.Z = IsZeroBit(result);
2632 APSR.C = carry;
2633 // APSR.V unchanged
2634#endif
2635
2636 return EmulateShiftReg(encoding, SRType_ROR);
2637}
2638
2639// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2640// with the carry flag shifted into bit [31].
2641//
2642// RRX can optionally update the condition flags based on the result.
2643// In that case, bit [0] is shifted into the carry flag.
2644bool
2645EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2646{
2647#if 0
2648 // ARM pseudo code...
2649 if ConditionPassed() then
2650 EncodingSpecificOperations();
2651 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2652 if d == 15 then // Can only occur for ARM encoding
2653 ALUWritePC(result); // setflags is always FALSE here
2654 else
2655 R[d] = result;
2656 if setflags then
2657 APSR.N = result<31>;
2658 APSR.Z = IsZeroBit(result);
2659 APSR.C = carry;
2660 // APSR.V unchanged
2661#endif
2662
2663 return EmulateShiftImm(encoding, SRType_RRX);
2664}
2665
Johnny Chen41a0a152011-02-16 01:27:54 +00002666bool
2667EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2668{
2669 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2670
Johnny Chen82f16aa2011-02-15 20:10:55 +00002671 bool success = false;
2672 const uint32_t opcode = OpcodeAsUnsigned (&success);
2673 if (!success)
2674 return false;
2675
2676 if (ConditionPassed())
2677 {
Johnny Chene7f89532011-02-15 23:22:46 +00002678 uint32_t Rd; // the destination register
2679 uint32_t Rm; // the first operand register
2680 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002681 uint32_t carry; // the carry bit after the shift operation
2682 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002683
2684 // Special case handling!
2685 // A8.6.139 ROR (immediate) -- Encoding T1
2686 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2687 {
2688 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2689 // have the same decoding of bit fields as the other Thumb2 shift operations.
2690 encoding = eEncodingT2;
2691 }
2692
Johnny Chen82f16aa2011-02-15 20:10:55 +00002693 switch (encoding) {
2694 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002695 // Due to the above special case handling!
2696 assert(shift_type != SRType_ROR);
2697
Johnny Chen82f16aa2011-02-15 20:10:55 +00002698 Rd = Bits32(opcode, 2, 0);
2699 Rm = Bits32(opcode, 5, 3);
2700 setflags = !InITBlock();
2701 imm5 = Bits32(opcode, 10, 6);
2702 break;
2703 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002704 // A8.6.141 RRX
2705 assert(shift_type != SRType_RRX);
2706
Johnny Chen82f16aa2011-02-15 20:10:55 +00002707 Rd = Bits32(opcode, 11, 8);
2708 Rm = Bits32(opcode, 3, 0);
2709 setflags = BitIsSet(opcode, 20);
2710 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2711 if (BadReg(Rd) || BadReg(Rm))
2712 return false;
2713 break;
2714 case eEncodingA1:
2715 Rd = Bits32(opcode, 15, 12);
2716 Rm = Bits32(opcode, 3, 0);
2717 setflags = BitIsSet(opcode, 20);
2718 imm5 = Bits32(opcode, 11, 7);
2719 break;
2720 default:
2721 return false;
2722 }
2723
Johnny Cheneeab4852011-02-16 22:14:44 +00002724 // A8.6.139 ROR (immediate)
2725 if (shift_type == SRType_ROR && imm5 == 0)
2726 shift_type = SRType_RRX;
2727
Johnny Chen82f16aa2011-02-15 20:10:55 +00002728 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002729 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002730 if (!success)
2731 return false;
2732
Johnny Cheneeab4852011-02-16 22:14:44 +00002733 // Decode the shift amount if not RRX.
2734 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002735
Johnny Chene97c0d52011-02-18 19:32:20 +00002736 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002737
2738 // The context specifies that an immediate is to be moved into Rd.
2739 EmulateInstruction::Context context;
2740 context.type = EmulateInstruction::eContextImmediate;
2741 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002742
Johnny Chen10530c22011-02-17 22:37:12 +00002743 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002744 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002745 }
2746 return true;
2747}
2748
Johnny Chene7f89532011-02-15 23:22:46 +00002749bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002750EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002751{
Johnny Chen41a0a152011-02-16 01:27:54 +00002752 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002753
2754 bool success = false;
2755 const uint32_t opcode = OpcodeAsUnsigned (&success);
2756 if (!success)
2757 return false;
2758
2759 if (ConditionPassed())
2760 {
2761 uint32_t Rd; // the destination register
2762 uint32_t Rn; // the first operand register
2763 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2764 uint32_t carry; // the carry bit after the shift operation
2765 bool setflags;
2766 switch (encoding) {
2767 case eEncodingT1:
2768 Rd = Bits32(opcode, 2, 0);
2769 Rn = Rd;
2770 Rm = Bits32(opcode, 5, 3);
2771 setflags = !InITBlock();
2772 break;
2773 case eEncodingT2:
2774 Rd = Bits32(opcode, 11, 8);
2775 Rn = Bits32(opcode, 19, 16);
2776 Rm = Bits32(opcode, 3, 0);
2777 setflags = BitIsSet(opcode, 20);
2778 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2779 return false;
2780 break;
2781 case eEncodingA1:
2782 Rd = Bits32(opcode, 15, 12);
2783 Rn = Bits32(opcode, 3, 0);
2784 Rm = Bits32(opcode, 11, 8);
2785 setflags = BitIsSet(opcode, 20);
2786 if (Rd == 15 || Rn == 15 || Rm == 15)
2787 return false;
2788 break;
2789 default:
2790 return false;
2791 }
2792
2793 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002794 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002795 if (!success)
2796 return false;
2797 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002798 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002799 if (!success)
2800 return false;
2801
2802 // Get the shift amount.
2803 uint32_t amt = Bits32(val, 7, 0);
2804
Johnny Chene97c0d52011-02-18 19:32:20 +00002805 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002806
2807 // The context specifies that an immediate is to be moved into Rd.
2808 EmulateInstruction::Context context;
2809 context.type = EmulateInstruction::eContextImmediate;
2810 context.SetNoArgs ();
2811
Johnny Chen10530c22011-02-17 22:37:12 +00002812 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002813 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002814 }
2815 return true;
2816}
2817
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002818// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002819// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002820// can be written back to the base register.
2821bool
2822EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2823{
2824#if 0
2825 // ARM pseudo code...
2826 if ConditionPassed()
2827 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2828 address = R[n];
2829
2830 for i = 0 to 14
2831 if registers<i> == '1' then
2832 R[i] = MemA[address, 4]; address = address + 4;
2833 if registers<15> == '1' then
2834 LoadWritePC (MemA[address, 4]);
2835
2836 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2837 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2838
2839#endif
2840
2841 bool success = false;
2842 const uint32_t opcode = OpcodeAsUnsigned (&success);
2843 if (!success)
2844 return false;
2845
2846 if (ConditionPassed())
2847 {
2848 uint32_t n;
2849 uint32_t registers = 0;
2850 bool wback;
2851 const uint32_t addr_byte_size = GetAddressByteSize();
2852 switch (encoding)
2853 {
2854 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002855 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002856 n = Bits32 (opcode, 10, 8);
2857 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002858 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002859 wback = BitIsClear (registers, n);
2860 // if BitCount(registers) < 1 then UNPREDICTABLE;
2861 if (BitCount(registers) < 1)
2862 return false;
2863 break;
2864 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002865 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2866 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002867 n = Bits32 (opcode, 19, 16);
2868 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002869 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002870 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002871
2872 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002873 if ((n == 15)
2874 || (BitCount (registers) < 2)
2875 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2876 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002877
2878 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002879 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002880 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002881
2882 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002883 if (wback
2884 && BitIsSet (registers, n))
2885 return false;
2886 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002887
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002888 case eEncodingA1:
2889 n = Bits32 (opcode, 19, 16);
2890 registers = Bits32 (opcode, 15, 0);
2891 wback = BitIsSet (opcode, 21);
2892 if ((n == 15)
2893 || (BitCount (registers) < 1))
2894 return false;
2895 break;
2896 default:
2897 return false;
2898 }
2899
2900 int32_t offset = 0;
2901 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2902 if (!success)
2903 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002904
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002905 EmulateInstruction::Context context;
2906 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2907 Register dwarf_reg;
2908 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2909 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002910
2911 for (int i = 0; i < 14; ++i)
2912 {
2913 if (BitIsSet (registers, i))
2914 {
Caroline Tice85aab332011-02-08 23:56:10 +00002915 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002916 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002917 if (wback && (n == 13)) // Pop Instruction
2918 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2919
2920 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002921 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002922 if (!success)
2923 return false;
2924
2925 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2926 return false;
2927
2928 offset += addr_byte_size;
2929 }
2930 }
2931
2932 if (BitIsSet (registers, 15))
2933 {
2934 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002935 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002936 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002937 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002938 if (!success)
2939 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002940 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002941 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002942 return false;
2943 }
2944
2945 if (wback && BitIsClear (registers, n))
2946 {
Caroline Ticefa172202011-02-11 22:49:54 +00002947 // R[n] = R[n] + 4 * BitCount (registers)
2948 int32_t offset = addr_byte_size * BitCount (registers);
2949 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002950 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002951
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2953 return false;
2954 }
2955 if (wback && BitIsSet (registers, n))
2956 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002957 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002958 }
2959 return true;
2960}
Caroline Tice713c2662011-02-11 17:59:55 +00002961
2962// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2963// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2964// can optionally be written back tot he base registers.
2965bool
2966EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2967{
2968#if 0
2969 // ARM pseudo code...
2970 if ConditionPassed() then
2971 EncodingSpecificOperations();
2972 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002973
Caroline Tice713c2662011-02-11 17:59:55 +00002974 for i = 0 to 14
2975 if registers<i> == ’1’ then
2976 R[i] = MemA[address,4]; address = address + 4;
2977
2978 if registers<15> == ’1’ then
2979 LoadWritePC(MemA[address,4]);
2980
2981 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2982 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2983#endif
2984
2985 bool success = false;
2986 const uint32_t opcode = OpcodeAsUnsigned (&success);
2987 if (!success)
2988 return false;
2989
2990 if (ConditionPassed())
2991 {
2992 uint32_t n;
2993 uint32_t registers = 0;
2994 bool wback;
2995 const uint32_t addr_byte_size = GetAddressByteSize();
2996
2997 // EncodingSpecificOperations();
2998 switch (encoding)
2999 {
3000 case eEncodingA1:
3001 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3002 n = Bits32 (opcode, 19, 16);
3003 registers = Bits32 (opcode, 15, 0);
3004 wback = BitIsSet (opcode, 21);
3005
3006 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3007 if ((n == 15) || (BitCount (registers) < 1))
3008 return false;
3009
3010 break;
3011
3012 default:
3013 return false;
3014 }
3015 // address = R[n] - 4*BitCount(registers) + 4;
3016
3017 int32_t offset = 0;
3018 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3019
3020 if (!success)
3021 return false;
3022
3023 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3024
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003025 EmulateInstruction::Context context;
3026 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3027 Register dwarf_reg;
3028 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3029 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003030
3031 // for i = 0 to 14
3032 for (int i = 0; i < 14; ++i)
3033 {
3034 // if registers<i> == ’1’ then
3035 if (BitIsSet (registers, i))
3036 {
3037 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003038 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003039 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003040 if (!success)
3041 return false;
3042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3043 return false;
3044 offset += addr_byte_size;
3045 }
3046 }
3047
3048 // if registers<15> == ’1’ then
3049 // LoadWritePC(MemA[address,4]);
3050 if (BitIsSet (registers, 15))
3051 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003052 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003053 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003054 if (!success)
3055 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003056 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003057 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003058 return false;
3059 }
3060
3061 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3062 if (wback && BitIsClear (registers, n))
3063 {
Caroline Tice713c2662011-02-11 17:59:55 +00003064 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3065 if (!success)
3066 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003067
3068 offset = (addr_byte_size * BitCount (registers)) * -1;
3069 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003070 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003071 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003072 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3073 return false;
3074 }
3075
3076 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3077 if (wback && BitIsSet (registers, n))
3078 return WriteBits32Unknown (n);
3079 }
3080 return true;
3081}
3082
3083// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3084// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3085// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003086bool
3087EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3088{
3089#if 0
3090 // ARM pseudo code...
3091 if ConditionPassed() then
3092 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3093 address = R[n] - 4*BitCount(registers);
3094
3095 for i = 0 to 14
3096 if registers<i> == ’1’ then
3097 R[i] = MemA[address,4]; address = address + 4;
3098 if registers<15> == ’1’ then
3099 LoadWritePC(MemA[address,4]);
3100
3101 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3102 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3103#endif
3104
3105 bool success = false;
3106 const uint32_t opcode = OpcodeAsUnsigned (&success);
3107 if (!success)
3108 return false;
3109
3110 if (ConditionPassed())
3111 {
3112 uint32_t n;
3113 uint32_t registers = 0;
3114 bool wback;
3115 const uint32_t addr_byte_size = GetAddressByteSize();
3116 switch (encoding)
3117 {
3118 case eEncodingT1:
3119 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3120 n = Bits32 (opcode, 19, 16);
3121 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003122 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003123 wback = BitIsSet (opcode, 21);
3124
3125 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3126 if ((n == 15)
3127 || (BitCount (registers) < 2)
3128 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3129 return false;
3130
3131 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003132 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003133 return false;
3134
3135 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3136 if (wback && BitIsSet (registers, n))
3137 return false;
3138
3139 break;
3140
3141 case eEncodingA1:
3142 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3143 n = Bits32 (opcode, 19, 16);
3144 registers = Bits32 (opcode, 15, 0);
3145 wback = BitIsSet (opcode, 21);
3146
3147 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3148 if ((n == 15) || (BitCount (registers) < 1))
3149 return false;
3150
3151 break;
3152
3153 default:
3154 return false;
3155 }
3156
Caroline Tice713c2662011-02-11 17:59:55 +00003157 // address = R[n] - 4*BitCount(registers);
3158
Caroline Tice0b29e242011-02-08 23:16:02 +00003159 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003160 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3161
3162 if (!success)
3163 return false;
3164
3165 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003166 EmulateInstruction::Context context;
3167 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3168 Register dwarf_reg;
3169 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3170 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003171
3172 for (int i = 0; i < 14; ++i)
3173 {
3174 if (BitIsSet (registers, i))
3175 {
3176 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003177 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003178 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003179 if (!success)
3180 return false;
3181
3182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3183 return false;
3184
3185 offset += addr_byte_size;
3186 }
3187 }
3188
3189 // if registers<15> == ’1’ then
3190 // LoadWritePC(MemA[address,4]);
3191 if (BitIsSet (registers, 15))
3192 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003193 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003194 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003195 if (!success)
3196 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003197 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003198 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003199 return false;
3200 }
3201
3202 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3203 if (wback && BitIsClear (registers, n))
3204 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003205 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3206 if (!success)
3207 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003208
3209 offset = (addr_byte_size * BitCount (registers)) * -1;
3210 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003211 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003212 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003213 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3214 return false;
3215 }
3216
3217 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3218 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003219 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003220 }
3221 return true;
3222}
Caroline Tice85aab332011-02-08 23:56:10 +00003223
Caroline Tice713c2662011-02-11 17:59:55 +00003224// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3225// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3226// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003227bool
3228EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3229{
3230#if 0
3231 if ConditionPassed() then
3232 EncodingSpecificOperations();
3233 address = R[n] + 4;
3234
3235 for i = 0 to 14
3236 if registers<i> == ’1’ then
3237 R[i] = MemA[address,4]; address = address + 4;
3238 if registers<15> == ’1’ then
3239 LoadWritePC(MemA[address,4]);
3240
3241 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3242 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3243#endif
3244
3245 bool success = false;
3246 const uint32_t opcode = OpcodeAsUnsigned (&success);
3247 if (!success)
3248 return false;
3249
3250 if (ConditionPassed())
3251 {
3252 uint32_t n;
3253 uint32_t registers = 0;
3254 bool wback;
3255 const uint32_t addr_byte_size = GetAddressByteSize();
3256 switch (encoding)
3257 {
3258 case eEncodingA1:
3259 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3260 n = Bits32 (opcode, 19, 16);
3261 registers = Bits32 (opcode, 15, 0);
3262 wback = BitIsSet (opcode, 21);
3263
3264 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3265 if ((n == 15) || (BitCount (registers) < 1))
3266 return false;
3267
3268 break;
3269 default:
3270 return false;
3271 }
3272 // address = R[n] + 4;
3273
3274 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003275 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3276
3277 if (!success)
3278 return false;
3279
3280 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003281
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003282 EmulateInstruction::Context context;
3283 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3284 Register dwarf_reg;
3285 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3286 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003287
3288 for (int i = 0; i < 14; ++i)
3289 {
3290 if (BitIsSet (registers, i))
3291 {
3292 // R[i] = MemA[address,4]; address = address + 4;
3293
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003294 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003295 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003296 if (!success)
3297 return false;
3298
3299 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3300 return false;
3301
3302 offset += addr_byte_size;
3303 }
3304 }
3305
3306 // if registers<15> == ’1’ then
3307 // LoadWritePC(MemA[address,4]);
3308 if (BitIsSet (registers, 15))
3309 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003310 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003311 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003312 if (!success)
3313 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003314 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003315 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003316 return false;
3317 }
3318
3319 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3320 if (wback && BitIsClear (registers, n))
3321 {
Caroline Tice85aab332011-02-08 23:56:10 +00003322 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3323 if (!success)
3324 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003325
3326 offset = addr_byte_size * BitCount (registers);
3327 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003328 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003329 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003330 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3331 return false;
3332 }
3333
3334 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3335 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003336 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003337 }
3338 return true;
3339}
Caroline Tice0b29e242011-02-08 23:16:02 +00003340
Johnny Chenef21b592011-02-10 01:52:38 +00003341// Load Register (immediate) calculates an address from a base register value and
3342// an immediate offset, loads a word from memory, and writes to a register.
3343// LDR (immediate, Thumb)
3344bool
3345EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3346{
3347#if 0
3348 // ARM pseudo code...
3349 if (ConditionPassed())
3350 {
3351 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3352 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3353 address = if index then offset_addr else R[n];
3354 data = MemU[address,4];
3355 if wback then R[n] = offset_addr;
3356 if t == 15 then
3357 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3358 elsif UnalignedSupport() || address<1:0> = '00' then
3359 R[t] = data;
3360 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3361 }
3362#endif
3363
3364 bool success = false;
3365 const uint32_t opcode = OpcodeAsUnsigned (&success);
3366 if (!success)
3367 return false;
3368
3369 if (ConditionPassed())
3370 {
3371 uint32_t Rt; // the destination register
3372 uint32_t Rn; // the base register
3373 uint32_t imm32; // the immediate offset used to form the address
3374 addr_t offset_addr; // the offset address
3375 addr_t address; // the calculated address
3376 uint32_t data; // the literal data value from memory load
3377 bool add, index, wback;
3378 switch (encoding) {
3379 case eEncodingT1:
3380 Rt = Bits32(opcode, 5, 3);
3381 Rn = Bits32(opcode, 2, 0);
3382 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3383 // index = TRUE; add = TRUE; wback = FALSE
3384 add = true;
3385 index = true;
3386 wback = false;
3387 break;
3388 default:
3389 return false;
3390 }
3391 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3392 if (!success)
3393 return false;
3394 if (add)
3395 offset_addr = base + imm32;
3396 else
3397 offset_addr = base - imm32;
3398
3399 address = (index ? offset_addr : base);
3400
3401 if (wback)
3402 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003403 EmulateInstruction::Context ctx;
3404 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3405 Register dwarf_reg;
3406 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3407 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3408
Johnny Chenef21b592011-02-10 01:52:38 +00003409 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3410 return false;
3411 }
3412
3413 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003414 EmulateInstruction::Context context;
3415 context.type = EmulateInstruction::eContextImmediate;
3416 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003417
3418 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003419 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003420 if (!success)
3421 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003422
3423 if (Rt == 15)
3424 {
3425 if (Bits32(address, 1, 0) == 0)
3426 {
Johnny Chen668b4512011-02-15 21:08:58 +00003427 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003428 return false;
3429 }
3430 else
3431 return false;
3432 }
3433 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3434 {
3435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3436 return false;
3437 }
3438 else
3439 return false;
3440 }
3441 return true;
3442}
3443
Caroline Ticeaf556562011-02-15 18:42:15 +00003444// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3445// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3446// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003447bool
3448EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3449{
3450#if 0
3451 if ConditionPassed() then
3452 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3453 address = R[n];
3454
3455 for i = 0 to 14
3456 if registers<i> == ’1’ then
3457 if i == n && wback && i != LowestSetBit(registers) then
3458 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3459 else
3460 MemA[address,4] = R[i];
3461 address = address + 4;
3462
3463 if registers<15> == ’1’ then // Only possible for encoding A1
3464 MemA[address,4] = PCStoreValue();
3465 if wback then R[n] = R[n] + 4*BitCount(registers);
3466#endif
3467
3468 bool success = false;
3469 const uint32_t opcode = OpcodeAsUnsigned (&success);
3470 if (!success)
3471 return false;
3472
3473 if (ConditionPassed ())
3474 {
3475 uint32_t n;
3476 uint32_t registers = 0;
3477 bool wback;
3478 const uint32_t addr_byte_size = GetAddressByteSize();
3479
3480 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3481 switch (encoding)
3482 {
3483 case eEncodingT1:
3484 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3485 n = Bits32 (opcode, 10, 8);
3486 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003487 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003488 wback = true;
3489
3490 // if BitCount(registers) < 1 then UNPREDICTABLE;
3491 if (BitCount (registers) < 1)
3492 return false;
3493
3494 break;
3495
3496 case eEncodingT2:
3497 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3498 n = Bits32 (opcode, 19, 16);
3499 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003500 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003501 wback = BitIsSet (opcode, 21);
3502
3503 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3504 if ((n == 15) || (BitCount (registers) < 2))
3505 return false;
3506
3507 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3508 if (wback && BitIsSet (registers, n))
3509 return false;
3510
3511 break;
3512
3513 case eEncodingA1:
3514 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3515 n = Bits32 (opcode, 19, 16);
3516 registers = Bits32 (opcode, 15, 0);
3517 wback = BitIsSet (opcode, 21);
3518
3519 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3520 if ((n == 15) || (BitCount (registers) < 1))
3521 return false;
3522
3523 break;
3524
3525 default:
3526 return false;
3527 }
3528
3529 // address = R[n];
3530 int32_t offset = 0;
3531 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3532 if (!success)
3533 return false;
3534
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003535 EmulateInstruction::Context context;
3536 context.type = EmulateInstruction::eContextRegisterStore;
3537 Register base_reg;
3538 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003539
3540 // for i = 0 to 14
3541 for (int i = 0; i < 14; ++i)
3542 {
3543 int lowest_set_bit = 14;
3544 // if registers<i> == ’1’ then
3545 if (BitIsSet (registers, i))
3546 {
3547 if (i < lowest_set_bit)
3548 lowest_set_bit = i;
3549 // if i == n && wback && i != LowestSetBit(registers) then
3550 if ((i == n) && wback && (i != lowest_set_bit))
3551 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3552 WriteBits32UnknownToMemory (address + offset);
3553 else
3554 {
3555 // MemA[address,4] = R[i];
3556 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3557 if (!success)
3558 return false;
3559
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003560 Register data_reg;
3561 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3562 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003563 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003564 return false;
3565 }
3566
3567 // address = address + 4;
3568 offset += addr_byte_size;
3569 }
3570 }
3571
3572 // if registers<15> == ’1’ then // Only possible for encoding A1
3573 // MemA[address,4] = PCStoreValue();
3574 if (BitIsSet (registers, 15))
3575 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003576 Register pc_reg;
3577 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3578 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003579 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3580 if (!success)
3581 return false;
3582
Caroline Ticecc96eb52011-02-17 19:20:40 +00003583 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003584 return false;
3585 }
3586
3587 // if wback then R[n] = R[n] + 4*BitCount(registers);
3588 if (wback)
3589 {
3590 offset = addr_byte_size * BitCount (registers);
3591 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003592 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003593 addr_t data = address + offset;
3594 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3595 return false;
3596 }
3597 }
3598 return true;
3599}
3600
Caroline Ticeaf556562011-02-15 18:42:15 +00003601// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3602// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3603// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003604bool
3605EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3606{
3607#if 0
3608 if ConditionPassed() then
3609 EncodingSpecificOperations();
3610 address = R[n] - 4*BitCount(registers) + 4;
3611
3612 for i = 0 to 14
3613 if registers<i> == ’1’ then
3614 if i == n && wback && i != LowestSetBit(registers) then
3615 MemA[address,4] = bits(32) UNKNOWN;
3616 else
3617 MemA[address,4] = R[i];
3618 address = address + 4;
3619
3620 if registers<15> == ’1’ then
3621 MemA[address,4] = PCStoreValue();
3622
3623 if wback then R[n] = R[n] - 4*BitCount(registers);
3624#endif
3625
3626 bool success = false;
3627 const uint32_t opcode = OpcodeAsUnsigned (&success);
3628 if (!success)
3629 return false;
3630
3631 if (ConditionPassed ())
3632 {
3633 uint32_t n;
3634 uint32_t registers = 0;
3635 bool wback;
3636 const uint32_t addr_byte_size = GetAddressByteSize();
3637
3638 // EncodingSpecificOperations();
3639 switch (encoding)
3640 {
3641 case eEncodingA1:
3642 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3643 n = Bits32 (opcode, 19, 16);
3644 registers = Bits32 (opcode, 15, 0);
3645 wback = BitIsSet (opcode, 21);
3646
3647 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3648 if ((n == 15) || (BitCount (registers) < 1))
3649 return false;
3650 break;
3651 default:
3652 return false;
3653 }
3654
3655 // address = R[n] - 4*BitCount(registers) + 4;
3656 int32_t offset = 0;
3657 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3658 if (!success)
3659 return false;
3660
3661 address = address - (addr_byte_size * BitCount (registers)) + 4;
3662
3663 EmulateInstruction::Context context;
3664 context.type = EmulateInstruction::eContextRegisterStore;
3665 Register base_reg;
3666 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3667
3668 // for i = 0 to 14
3669 for (int i = 0; i < 14; ++i)
3670 {
3671 int lowest_bit_set = 14;
3672 // if registers<i> == ’1’ then
3673 if (BitIsSet (registers, i))
3674 {
3675 if (i < lowest_bit_set)
3676 lowest_bit_set = i;
3677 //if i == n && wback && i != LowestSetBit(registers) then
3678 if ((i == n) && wback && (i != lowest_bit_set))
3679 // MemA[address,4] = bits(32) UNKNOWN;
3680 WriteBits32UnknownToMemory (address + offset);
3681 else
3682 {
3683 // MemA[address,4] = R[i];
3684 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3685 if (!success)
3686 return false;
3687
3688 Register data_reg;
3689 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3690 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003691 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003692 return false;
3693 }
3694
3695 // address = address + 4;
3696 offset += addr_byte_size;
3697 }
3698 }
3699
3700 // if registers<15> == ’1’ then
3701 // MemA[address,4] = PCStoreValue();
3702 if (BitIsSet (registers, 15))
3703 {
3704 Register pc_reg;
3705 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3706 context.SetRegisterPlusOffset (pc_reg, 8);
3707 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3708 if (!success)
3709 return false;
3710
Caroline Ticecc96eb52011-02-17 19:20:40 +00003711 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003712 return false;
3713 }
3714
3715 // if wback then R[n] = R[n] - 4*BitCount(registers);
3716 if (wback)
3717 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003718 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003719 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3720 context.SetImmediateSigned (offset);
3721 addr_t data = address + offset;
3722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3723 return false;
3724 }
3725 }
3726 return true;
3727}
3728
Caroline Ticeaf556562011-02-15 18:42:15 +00003729// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3730// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3731// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003732bool
3733EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3734{
3735#if 0
3736 if ConditionPassed() then
3737 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3738 address = R[n] - 4*BitCount(registers);
3739
3740 for i = 0 to 14
3741 if registers<i> == ’1’ then
3742 if i == n && wback && i != LowestSetBit(registers) then
3743 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3744 else
3745 MemA[address,4] = R[i];
3746 address = address + 4;
3747
3748 if registers<15> == ’1’ then // Only possible for encoding A1
3749 MemA[address,4] = PCStoreValue();
3750
3751 if wback then R[n] = R[n] - 4*BitCount(registers);
3752#endif
3753
3754
3755 bool success = false;
3756 const uint32_t opcode = OpcodeAsUnsigned (&success);
3757 if (!success)
3758 return false;
3759
3760 if (ConditionPassed ())
3761 {
3762 uint32_t n;
3763 uint32_t registers = 0;
3764 bool wback;
3765 const uint32_t addr_byte_size = GetAddressByteSize();
3766
3767 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3768 switch (encoding)
3769 {
3770 case eEncodingT1:
3771 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3772 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3773 {
3774 // See PUSH
3775 }
3776 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3777 n = Bits32 (opcode, 19, 16);
3778 registers = Bits32 (opcode, 15, 0);
3779 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3780 wback = BitIsSet (opcode, 21);
3781 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3782 if ((n == 15) || BitCount (registers) < 2)
3783 return false;
3784 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3785 if (wback && BitIsSet (registers, n))
3786 return false;
3787 break;
3788
3789 case eEncodingA1:
3790 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3791 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3792 {
3793 // See Push
3794 }
3795 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3796 n = Bits32 (opcode, 19, 16);
3797 registers = Bits32 (opcode, 15, 0);
3798 wback = BitIsSet (opcode, 21);
3799 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3800 if ((n == 15) || BitCount (registers) < 1)
3801 return false;
3802 break;
3803
3804 default:
3805 return false;
3806 }
3807
3808 // address = R[n] - 4*BitCount(registers);
3809
3810 int32_t offset = 0;
3811 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3812 if (!success)
3813 return false;
3814
3815 address = address - (addr_byte_size * BitCount (registers));
3816
3817 EmulateInstruction::Context context;
3818 context.type = EmulateInstruction::eContextRegisterStore;
3819 Register base_reg;
3820 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3821
3822 // for i = 0 to 14
3823 for (int i = 0; i < 14; ++i)
3824 {
3825 uint32_t lowest_set_bit = 14;
3826 // if registers<i> == ’1’ then
3827 if (BitIsSet (registers, i))
3828 {
3829 if (i < lowest_set_bit)
3830 lowest_set_bit = i;
3831 // if i == n && wback && i != LowestSetBit(registers) then
3832 if ((i == n) && wback && (i != lowest_set_bit))
3833 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3834 WriteBits32UnknownToMemory (address + offset);
3835 else
3836 {
3837 // MemA[address,4] = R[i];
3838 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3839 if (!success)
3840 return false;
3841
3842 Register data_reg;
3843 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3844 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003845 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003846 return false;
3847 }
3848
3849 // address = address + 4;
3850 offset += addr_byte_size;
3851 }
3852 }
3853
3854 // if registers<15> == ’1’ then // Only possible for encoding A1
3855 // MemA[address,4] = PCStoreValue();
3856 if (BitIsSet (registers, 15))
3857 {
3858 Register pc_reg;
3859 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3860 context.SetRegisterPlusOffset (pc_reg, 8);
3861 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3862 if (!success)
3863 return false;
3864
Caroline Ticecc96eb52011-02-17 19:20:40 +00003865 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003866 return false;
3867 }
3868
3869 // if wback then R[n] = R[n] - 4*BitCount(registers);
3870 if (wback)
3871 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003872 offset = (addr_byte_size * BitCount (registers)) * -1;
3873 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3874 context.SetImmediateSigned (offset);
3875 addr_t data = address + offset;
3876 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3877 return false;
3878 }
3879 }
3880 return true;
3881}
3882
3883// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3884// from a base register. The consecutive memory locations start just above this address, and the address of the last
3885// of those locations can optionally be written back to the base register.
3886bool
3887EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3888{
3889#if 0
3890 if ConditionPassed() then
3891 EncodingSpecificOperations();
3892 address = R[n] + 4;
3893
3894 for i = 0 to 14
3895 if registers<i> == ’1’ then
3896 if i == n && wback && i != LowestSetBit(registers) then
3897 MemA[address,4] = bits(32) UNKNOWN;
3898 else
3899 MemA[address,4] = R[i];
3900 address = address + 4;
3901
3902 if registers<15> == ’1’ then
3903 MemA[address,4] = PCStoreValue();
3904
3905 if wback then R[n] = R[n] + 4*BitCount(registers);
3906#endif
3907
3908 bool success = false;
3909 const uint32_t opcode = OpcodeAsUnsigned (&success);
3910 if (!success)
3911 return false;
3912
3913 if (ConditionPassed())
3914 {
3915 uint32_t n;
3916 uint32_t registers = 0;
3917 bool wback;
3918 const uint32_t addr_byte_size = GetAddressByteSize();
3919
3920 // EncodingSpecificOperations();
3921 switch (encoding)
3922 {
3923 case eEncodingA1:
3924 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3925 n = Bits32 (opcode, 19, 16);
3926 registers = Bits32 (opcode, 15, 0);
3927 wback = BitIsSet (opcode, 21);
3928
3929 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3930 if ((n == 15) && (BitCount (registers) < 1))
3931 return false;
3932 break;
3933 default:
3934 return false;
3935 }
3936 // address = R[n] + 4;
3937
3938 int32_t offset = 0;
3939 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3940 if (!success)
3941 return false;
3942
3943 address = address + addr_byte_size;
3944
3945 EmulateInstruction::Context context;
3946 context.type = EmulateInstruction::eContextRegisterStore;
3947 Register base_reg;
3948 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3949
3950 uint32_t lowest_set_bit = 14;
3951 // for i = 0 to 14
3952 for (int i = 0; i < 14; ++i)
3953 {
3954 // if registers<i> == ’1’ then
3955 if (BitIsSet (registers, i))
3956 {
3957 if (i < lowest_set_bit)
3958 lowest_set_bit = i;
3959 // if i == n && wback && i != LowestSetBit(registers) then
3960 if ((i == n) && wback && (i != lowest_set_bit))
3961 // MemA[address,4] = bits(32) UNKNOWN;
3962 WriteBits32UnknownToMemory (address + offset);
3963 // else
3964 else
3965 {
3966 // MemA[address,4] = R[i];
3967 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3968 if (!success)
3969 return false;
3970
3971 Register data_reg;
3972 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3973 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003974 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003975 return false;
3976 }
3977
3978 // address = address + 4;
3979 offset += addr_byte_size;
3980 }
3981 }
3982
3983 // if registers<15> == ’1’ then
3984 // MemA[address,4] = PCStoreValue();
3985 if (BitIsSet (registers, 15))
3986 {
3987 Register pc_reg;
3988 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3989 context.SetRegisterPlusOffset (pc_reg, 8);
3990 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3991 if (!success)
3992 return false;
3993
Caroline Ticecc96eb52011-02-17 19:20:40 +00003994 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003995 return false;
3996 }
3997
3998 // if wback then R[n] = R[n] + 4*BitCount(registers);
3999 if (wback)
4000 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004001 offset = addr_byte_size * BitCount (registers);
4002 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4003 context.SetImmediateSigned (offset);
4004 addr_t data = address + offset;
4005 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4006 return false;
4007 }
4008 }
4009 return true;
4010}
Caroline Tice7fac8572011-02-15 22:53:54 +00004011
4012// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4013// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4014bool
4015EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4016{
4017#if 0
4018 if ConditionPassed() then
4019 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4020 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4021 address = if index then offset_addr else R[n];
4022 if UnalignedSupport() || address<1:0> == ’00’ then
4023 MemU[address,4] = R[t];
4024 else // Can only occur before ARMv7
4025 MemU[address,4] = bits(32) UNKNOWN;
4026 if wback then R[n] = offset_addr;
4027#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004028
Caroline Tice7fac8572011-02-15 22:53:54 +00004029 bool success = false;
4030 const uint32_t opcode = OpcodeAsUnsigned (&success);
4031 if (!success)
4032 return false;
4033
4034 if (ConditionPassed())
4035 {
4036 const uint32_t addr_byte_size = GetAddressByteSize();
4037
4038 uint32_t t;
4039 uint32_t n;
4040 uint32_t imm32;
4041 bool index;
4042 bool add;
4043 bool wback;
4044 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4045 switch (encoding)
4046 {
4047 case eEncodingT1:
4048 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4049 t = Bits32 (opcode, 2, 0);
4050 n = Bits32 (opcode, 5, 3);
4051 imm32 = Bits32 (opcode, 10, 6) << 2;
4052
4053 // index = TRUE; add = TRUE; wback = FALSE;
4054 index = true;
4055 add = false;
4056 wback = false;
4057 break;
4058
4059 case eEncodingT2:
4060 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4061 t = Bits32 (opcode, 10, 8);
4062 n = 13;
4063 imm32 = Bits32 (opcode, 7, 0) << 2;
4064
4065 // index = TRUE; add = TRUE; wback = FALSE;
4066 index = true;
4067 add = true;
4068 wback = false;
4069 break;
4070
4071 case eEncodingT3:
4072 // if Rn == ’1111’ then UNDEFINED;
4073 if (Bits32 (opcode, 19, 16) == 15)
4074 return false;
4075
4076 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4077 t = Bits32 (opcode, 15, 12);
4078 n = Bits32 (opcode, 19, 16);
4079 imm32 = Bits32 (opcode, 11, 0);
4080
4081 // index = TRUE; add = TRUE; wback = FALSE;
4082 index = true;
4083 add = true;
4084 wback = false;
4085
4086 // if t == 15 then UNPREDICTABLE;
4087 if (t == 15)
4088 return false;
4089 break;
4090
4091 case eEncodingT4:
4092 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4093 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4094 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4095 if ((Bits32 (opcode, 19, 16) == 15)
4096 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4097 return false;
4098
4099 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4100 t = Bits32 (opcode, 15, 12);
4101 n = Bits32 (opcode, 19, 16);
4102 imm32 = Bits32 (opcode, 7, 0);
4103
4104 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4105 index = BitIsSet (opcode, 10);
4106 add = BitIsSet (opcode, 9);
4107 wback = BitIsSet (opcode, 8);
4108
4109 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4110 if ((t == 15) || (wback && (n == t)))
4111 return false;
4112 break;
4113
4114 default:
4115 return false;
4116 }
4117
4118 addr_t offset_addr;
4119 addr_t address;
4120
4121 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4122 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4123 if (!success)
4124 return false;
4125
4126 if (add)
4127 offset_addr = base_address + imm32;
4128 else
4129 offset_addr = base_address - imm32;
4130
4131 // address = if index then offset_addr else R[n];
4132 if (index)
4133 address = offset_addr;
4134 else
4135 address = base_address;
4136
4137 EmulateInstruction::Context context;
4138 context.type = eContextRegisterStore;
4139 Register base_reg;
4140 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4141
4142 // if UnalignedSupport() || address<1:0> == ’00’ then
4143 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4144 {
4145 // MemU[address,4] = R[t];
4146 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4147 if (!success)
4148 return false;
4149
4150 Register data_reg;
4151 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4152 int32_t offset = address - base_address;
4153 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004154 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004155 return false;
4156 }
4157 else
4158 {
4159 // MemU[address,4] = bits(32) UNKNOWN;
4160 WriteBits32UnknownToMemory (address);
4161 }
4162
4163 // if wback then R[n] = offset_addr;
4164 if (wback)
4165 {
4166 context.type = eContextRegisterLoad;
4167 context.SetAddress (offset_addr);
4168 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4169 return false;
4170 }
4171 }
4172 return true;
4173}
Caroline Ticeaf556562011-02-15 18:42:15 +00004174
Caroline Tice3fd63e92011-02-16 00:33:43 +00004175// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4176// word from a register to memory. The offset register value can optionally be shifted.
4177bool
4178EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4179{
4180#if 0
4181 if ConditionPassed() then
4182 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4183 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4184 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4185 address = if index then offset_addr else R[n];
4186 if t == 15 then // Only possible for encoding A1
4187 data = PCStoreValue();
4188 else
4189 data = R[t];
4190 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4191 MemU[address,4] = data;
4192 else // Can only occur before ARMv7
4193 MemU[address,4] = bits(32) UNKNOWN;
4194 if wback then R[n] = offset_addr;
4195#endif
4196
4197 bool success = false;
4198 const uint32_t opcode = OpcodeAsUnsigned (&success);
4199 if (!success)
4200 return false;
4201
4202 if (ConditionPassed())
4203 {
4204 const uint32_t addr_byte_size = GetAddressByteSize();
4205
4206 uint32_t t;
4207 uint32_t n;
4208 uint32_t m;
4209 ARM_ShifterType shift_t;
4210 uint32_t shift_n;
4211 bool index;
4212 bool add;
4213 bool wback;
4214
4215 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4216 switch (encoding)
4217 {
4218 case eEncodingT1:
4219 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4220 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4221 t = Bits32 (opcode, 2, 0);
4222 n = Bits32 (opcode, 5, 3);
4223 m = Bits32 (opcode, 8, 6);
4224
4225 // index = TRUE; add = TRUE; wback = FALSE;
4226 index = true;
4227 add = true;
4228 wback = false;
4229
4230 // (shift_t, shift_n) = (SRType_LSL, 0);
4231 shift_t = SRType_LSL;
4232 shift_n = 0;
4233 break;
4234
4235 case eEncodingT2:
4236 // if Rn == ’1111’ then UNDEFINED;
4237 if (Bits32 (opcode, 19, 16) == 15)
4238 return false;
4239
4240 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4241 t = Bits32 (opcode, 15, 12);
4242 n = Bits32 (opcode, 19, 16);
4243 m = Bits32 (opcode, 3, 0);
4244
4245 // index = TRUE; add = TRUE; wback = FALSE;
4246 index = true;
4247 add = true;
4248 wback = false;
4249
4250 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4251 shift_t = SRType_LSL;
4252 shift_n = Bits32 (opcode, 5, 4);
4253
4254 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4255 if ((t == 15) || (BadReg (m)))
4256 return false;
4257 break;
4258
4259 case eEncodingA1:
4260 {
4261 // if P == ’0’ && W == ’1’ then SEE STRT;
4262 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4263 t = Bits32 (opcode, 15, 12);
4264 n = Bits32 (opcode, 19, 16);
4265 m = Bits32 (opcode, 3, 0);
4266
4267 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4268 index = BitIsSet (opcode, 24);
4269 add = BitIsSet (opcode, 23);
4270 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4271
4272 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4273 uint32_t typ = Bits32 (opcode, 6, 5);
4274 uint32_t imm5 = Bits32 (opcode, 11, 7);
4275 shift_n = DecodeImmShift(typ, imm5, shift_t);
4276
4277 // if m == 15 then UNPREDICTABLE;
4278 if (m == 15)
4279 return false;
4280
4281 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4282 if (wback && ((n == 15) || (n == t)))
4283 return false;
4284
4285 break;
4286 }
4287 default:
4288 return false;
4289 }
4290
4291 addr_t offset_addr;
4292 addr_t address;
4293 int32_t offset = 0;
4294
4295 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4296 if (!success)
4297 return false;
4298
4299 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4300 if (!success)
4301 return false;
4302
4303 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004304 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004305
4306 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4307 if (add)
4308 offset_addr = base_address + offset;
4309 else
4310 offset_addr = base_address - offset;
4311
4312 // address = if index then offset_addr else R[n];
4313 if (index)
4314 address = offset_addr;
4315 else
4316 address = base_address;
4317
4318 uint32_t data;
4319 // if t == 15 then // Only possible for encoding A1
4320 if (t == 15)
4321 // data = PCStoreValue();
4322 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4323 else
4324 // data = R[t];
4325 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4326
4327 if (!success)
4328 return false;
4329
4330 EmulateInstruction::Context context;
4331 context.type = eContextRegisterStore;
4332
4333 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4334 if (UnalignedSupport ()
4335 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4336 || CurrentInstrSet() == eModeARM)
4337 {
4338 // MemU[address,4] = data;
4339
4340 Register base_reg;
4341 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4342
4343 Register data_reg;
4344 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4345
4346 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004347 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004348 return false;
4349
4350 }
4351 else
4352 // MemU[address,4] = bits(32) UNKNOWN;
4353 WriteBits32UnknownToMemory (address);
4354
4355 // if wback then R[n] = offset_addr;
4356 if (wback)
4357 {
4358 context.type = eContextRegisterLoad;
4359 context.SetAddress (offset_addr);
4360 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4361 return false;
4362 }
4363
4364 }
4365 return true;
4366}
Caroline Tice73a29de2011-02-16 20:22:22 +00004367
4368bool
4369EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4370{
4371#if 0
4372 if ConditionPassed() then
4373 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4374 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4375 address = if index then offset_addr else R[n];
4376 MemU[address,1] = R[t]<7:0>;
4377 if wback then R[n] = offset_addr;
4378#endif
4379
4380
4381 bool success = false;
4382 const uint32_t opcode = OpcodeAsUnsigned (&success);
4383 if (!success)
4384 return false;
4385
4386 if (ConditionPassed ())
4387 {
4388 uint32_t t;
4389 uint32_t n;
4390 uint32_t imm32;
4391 bool index;
4392 bool add;
4393 bool wback;
4394 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4395 switch (encoding)
4396 {
4397 case eEncodingT1:
4398 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4399 t = Bits32 (opcode, 2, 0);
4400 n = Bits32 (opcode, 5, 3);
4401 imm32 = Bits32 (opcode, 10, 6);
4402
4403 // index = TRUE; add = TRUE; wback = FALSE;
4404 index = true;
4405 add = true;
4406 wback = false;
4407 break;
4408
4409 case eEncodingT2:
4410 // if Rn == ’1111’ then UNDEFINED;
4411 if (Bits32 (opcode, 19, 16) == 15)
4412 return false;
4413
4414 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4415 t = Bits32 (opcode, 15, 12);
4416 n = Bits32 (opcode, 19, 16);
4417 imm32 = Bits32 (opcode, 11, 0);
4418
4419 // index = TRUE; add = TRUE; wback = FALSE;
4420 index = true;
4421 add = true;
4422 wback = false;
4423
4424 // if BadReg(t) then UNPREDICTABLE;
4425 if (BadReg (t))
4426 return false;
4427 break;
4428
4429 case eEncodingT3:
4430 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4431 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4432 if (Bits32 (opcode, 19, 16) == 15)
4433 return false;
4434
4435 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4436 t = Bits32 (opcode, 15, 12);
4437 n = Bits32 (opcode, 19, 16);
4438 imm32 = Bits32 (opcode, 7, 0);
4439
4440 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4441 index = BitIsSet (opcode, 10);
4442 add = BitIsSet (opcode, 9);
4443 wback = BitIsSet (opcode, 8);
4444
4445 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4446 if ((BadReg (t)) || (wback && (n == t)))
4447 return false;
4448 break;
4449
4450 default:
4451 return false;
4452 }
4453
4454 addr_t offset_addr;
4455 addr_t address;
4456 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4457 if (!success)
4458 return false;
4459
4460 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4461 if (add)
4462 offset_addr = base_address + imm32;
4463 else
4464 offset_addr = base_address - imm32;
4465
4466 // address = if index then offset_addr else R[n];
4467 if (index)
4468 address = offset_addr;
4469 else
4470 address = base_address;
4471
Caroline Ticecc96eb52011-02-17 19:20:40 +00004472 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004473 Register base_reg;
4474 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4475
4476 Register data_reg;
4477 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4478
4479 EmulateInstruction::Context context;
4480 context.type = eContextRegisterStore;
4481 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4482
4483 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4484 if (!success)
4485 return false;
4486
4487 data = Bits32 (data, 7, 0);
4488
Caroline Ticecc96eb52011-02-17 19:20:40 +00004489 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004490 return false;
4491
4492 // if wback then R[n] = offset_addr;
4493 if (wback)
4494 {
4495 context.type = eContextRegisterLoad;
4496 context.SetAddress (offset_addr);
4497 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4498 return false;
4499 }
4500
4501 }
4502
4503 return true;
4504}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004505
Johnny Chen157b9592011-02-18 21:13:05 +00004506// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4507// and writes the result to the destination register. It can optionally update the condition flags
4508// based on the result.
4509bool
4510EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4511{
4512#if 0
4513 // ARM pseudo code...
4514 if ConditionPassed() then
4515 EncodingSpecificOperations();
4516 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4517 if d == 15 then // Can only occur for ARM encoding
4518 ALUWritePC(result); // setflags is always FALSE here
4519 else
4520 R[d] = result;
4521 if setflags then
4522 APSR.N = result<31>;
4523 APSR.Z = IsZeroBit(result);
4524 APSR.C = carry;
4525 APSR.V = overflow;
4526#endif
4527
4528 bool success = false;
4529 const uint32_t opcode = OpcodeAsUnsigned (&success);
4530 if (!success)
4531 return false;
4532
4533 if (ConditionPassed())
4534 {
4535 uint32_t Rd, Rn;
4536 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4537 bool setflags;
4538 switch (encoding)
4539 {
4540 case eEncodingT1:
4541 Rd = Bits32(opcode, 11, 8);
4542 Rn = Bits32(opcode, 19, 16);
4543 setflags = BitIsSet(opcode, 20);
4544 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4545 if (BadReg(Rd) || BadReg(Rn))
4546 return false;
4547 break;
4548 case eEncodingA1:
4549 Rd = Bits32(opcode, 15, 12);
4550 Rn = Bits32(opcode, 19, 16);
4551 setflags = BitIsSet(opcode, 20);
4552 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4553 // TODO: Emulate SUBS PC, LR and related instructions.
4554 if (Rd == 15 && setflags)
4555 return false;
4556 break;
4557 default:
4558 return false;
4559 }
4560
4561 // Read the first operand.
4562 int32_t val1 = ReadCoreReg(Rn, &success);
4563 if (!success)
4564 return false;
4565
4566 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4567
4568 EmulateInstruction::Context context;
4569 context.type = EmulateInstruction::eContextImmediate;
4570 context.SetNoArgs ();
4571
4572 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4573 return false;
4574 }
4575 return true;
4576}
4577
4578// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4579// register value, and writes the result to the destination register. It can optionally update the
4580// condition flags based on the result.
4581bool
4582EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4583{
4584#if 0
4585 // ARM pseudo code...
4586 if ConditionPassed() then
4587 EncodingSpecificOperations();
4588 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4589 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4590 if d == 15 then // Can only occur for ARM encoding
4591 ALUWritePC(result); // setflags is always FALSE here
4592 else
4593 R[d] = result;
4594 if setflags then
4595 APSR.N = result<31>;
4596 APSR.Z = IsZeroBit(result);
4597 APSR.C = carry;
4598 APSR.V = overflow;
4599#endif
4600
4601 bool success = false;
4602 const uint32_t opcode = OpcodeAsUnsigned (&success);
4603 if (!success)
4604 return false;
4605
4606 if (ConditionPassed())
4607 {
4608 uint32_t Rd, Rn, Rm;
4609 ARM_ShifterType shift_t;
4610 uint32_t shift_n; // the shift applied to the value read from Rm
4611 bool setflags;
4612 switch (encoding)
4613 {
4614 case eEncodingT1:
4615 Rd = Rn = Bits32(opcode, 2, 0);
4616 Rm = Bits32(opcode, 5, 3);
4617 setflags = !InITBlock();
4618 shift_t = SRType_LSL;
4619 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004620 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004621 case eEncodingT2:
4622 Rd = Bits32(opcode, 11, 8);
4623 Rn = Bits32(opcode, 19, 16);
4624 Rm = Bits32(opcode, 3, 0);
4625 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004626 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004627 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4628 return false;
4629 break;
4630 case eEncodingA1:
4631 Rd = Bits32(opcode, 15, 12);
4632 Rn = Bits32(opcode, 19, 16);
4633 Rm = Bits32(opcode, 3, 0);
4634 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004635 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004636 // TODO: Emulate SUBS PC, LR and related instructions.
4637 if (Rd == 15 && setflags)
4638 return false;
4639 break;
4640 default:
4641 return false;
4642 }
4643
4644 // Read the first operand.
4645 int32_t val1 = ReadCoreReg(Rn, &success);
4646 if (!success)
4647 return false;
4648
4649 // Read the second operand.
4650 int32_t val2 = ReadCoreReg(Rm, &success);
4651 if (!success)
4652 return false;
4653
4654 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4655 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4656
4657 EmulateInstruction::Context context;
4658 context.type = EmulateInstruction::eContextImmediate;
4659 context.SetNoArgs ();
4660
4661 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4662 return false;
4663 }
4664 return true;
4665}
4666
Johnny Chene97c0d52011-02-18 19:32:20 +00004667// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4668// to the destination register. It can optionally update the condition flags based on the result.
4669bool
4670EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4671{
4672#if 0
4673 // ARM pseudo code...
4674 if ConditionPassed() then
4675 EncodingSpecificOperations();
4676 result = R[n] AND imm32;
4677 if d == 15 then // Can only occur for ARM encoding
4678 ALUWritePC(result); // setflags is always FALSE here
4679 else
4680 R[d] = result;
4681 if setflags then
4682 APSR.N = result<31>;
4683 APSR.Z = IsZeroBit(result);
4684 APSR.C = carry;
4685 // APSR.V unchanged
4686#endif
4687
4688 bool success = false;
4689 const uint32_t opcode = OpcodeAsUnsigned (&success);
4690 if (!success)
4691 return false;
4692
4693 if (ConditionPassed())
4694 {
4695 uint32_t Rd, Rn;
4696 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4697 bool setflags;
4698 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4699 switch (encoding)
4700 {
4701 case eEncodingT1:
4702 Rd = Bits32(opcode, 11, 8);
4703 Rn = Bits32(opcode, 19, 16);
4704 setflags = BitIsSet(opcode, 20);
4705 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004706 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004707 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004708 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004709 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4710 return false;
4711 break;
4712 case eEncodingA1:
4713 Rd = Bits32(opcode, 15, 12);
4714 Rn = Bits32(opcode, 19, 16);
4715 setflags = BitIsSet(opcode, 20);
4716 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4717 // TODO: Emulate SUBS PC, LR and related instructions.
4718 if (Rd == 15 && setflags)
4719 return false;
4720 break;
4721 default:
4722 return false;
4723 }
4724
Johnny Chene97c0d52011-02-18 19:32:20 +00004725 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004726 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004727 if (!success)
4728 return false;
4729
4730 uint32_t result = val1 & imm32;
4731
4732 EmulateInstruction::Context context;
4733 context.type = EmulateInstruction::eContextImmediate;
4734 context.SetNoArgs ();
4735
4736 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4737 return false;
4738 }
4739 return true;
4740}
4741
4742// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4743// and writes the result to the destination register. It can optionally update the condition flags
4744// based on the result.
4745bool
4746EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4747{
4748#if 0
4749 // ARM pseudo code...
4750 if ConditionPassed() then
4751 EncodingSpecificOperations();
4752 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4753 result = R[n] AND shifted;
4754 if d == 15 then // Can only occur for ARM encoding
4755 ALUWritePC(result); // setflags is always FALSE here
4756 else
4757 R[d] = result;
4758 if setflags then
4759 APSR.N = result<31>;
4760 APSR.Z = IsZeroBit(result);
4761 APSR.C = carry;
4762 // APSR.V unchanged
4763#endif
4764
4765 bool success = false;
4766 const uint32_t opcode = OpcodeAsUnsigned (&success);
4767 if (!success)
4768 return false;
4769
4770 if (ConditionPassed())
4771 {
4772 uint32_t Rd, Rn, Rm;
4773 ARM_ShifterType shift_t;
4774 uint32_t shift_n; // the shift applied to the value read from Rm
4775 bool setflags;
4776 uint32_t carry;
4777 switch (encoding)
4778 {
4779 case eEncodingT1:
4780 Rd = Rn = Bits32(opcode, 2, 0);
4781 Rm = Bits32(opcode, 5, 3);
4782 setflags = !InITBlock();
4783 shift_t = SRType_LSL;
4784 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004785 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004786 case eEncodingT2:
4787 Rd = Bits32(opcode, 11, 8);
4788 Rn = Bits32(opcode, 19, 16);
4789 Rm = Bits32(opcode, 3, 0);
4790 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004791 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004792 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004793 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004794 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004795 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4796 return false;
4797 break;
4798 case eEncodingA1:
4799 Rd = Bits32(opcode, 15, 12);
4800 Rn = Bits32(opcode, 19, 16);
4801 Rm = Bits32(opcode, 3, 0);
4802 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004803 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004804 // TODO: Emulate SUBS PC, LR and related instructions.
4805 if (Rd == 15 && setflags)
4806 return false;
4807 break;
4808 default:
4809 return false;
4810 }
4811
Johnny Chene97c0d52011-02-18 19:32:20 +00004812 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004813 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004814 if (!success)
4815 return false;
4816
4817 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004818 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004819 if (!success)
4820 return false;
4821
4822 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4823 uint32_t result = val1 & shifted;
4824
4825 EmulateInstruction::Context context;
4826 context.type = EmulateInstruction::eContextImmediate;
4827 context.SetNoArgs ();
4828
4829 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4830 return false;
4831 }
4832 return true;
4833}
4834
Caroline Tice4d729c52011-02-18 00:55:53 +00004835// 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 +00004836// 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 +00004837bool
4838EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4839{
4840#if 0
4841 if ConditionPassed() then
4842 EncodingSpecificOperations();
4843 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4844 address = if index then offset_addr else R[n];
4845 data = MemU[address,4];
4846 if wback then R[n] = offset_addr;
4847 if t == 15 then
4848 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4849 elsif UnalignedSupport() || address<1:0> = ’00’ then
4850 R[t] = data;
4851 else // Can only apply before ARMv7
4852 R[t] = ROR(data, 8*UInt(address<1:0>));
4853#endif
4854
4855 bool success = false;
4856 const uint32_t opcode = OpcodeAsUnsigned (&success);
4857 if (!success)
4858 return false;
4859
4860 if (ConditionPassed ())
4861 {
4862 const uint32_t addr_byte_size = GetAddressByteSize();
4863
4864 uint32_t t;
4865 uint32_t n;
4866 uint32_t imm32;
4867 bool index;
4868 bool add;
4869 bool wback;
4870
4871 switch (encoding)
4872 {
4873 case eEncodingA1:
4874 // if Rn == ’1111’ then SEE LDR (literal);
4875 // if P == ’0’ && W == ’1’ then SEE LDRT;
4876 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4877 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4878 t = Bits32 (opcode, 15, 12);
4879 n = Bits32 (opcode, 19, 16);
4880 imm32 = Bits32 (opcode, 11, 0);
4881
4882 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4883 index = BitIsSet (opcode, 24);
4884 add = BitIsSet (opcode, 23);
4885 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4886
4887 // if wback && n == t then UNPREDICTABLE;
4888 if (wback && (n == t))
4889 return false;
4890
4891 break;
4892
4893 default:
4894 return false;
4895 }
4896
4897 addr_t address;
4898 addr_t offset_addr;
4899 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4900 if (!success)
4901 return false;
4902
4903 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4904 if (add)
4905 offset_addr = base_address + imm32;
4906 else
4907 offset_addr = base_address - imm32;
4908
4909 // address = if index then offset_addr else R[n];
4910 if (index)
4911 address = offset_addr;
4912 else
4913 address = base_address;
4914
4915 // data = MemU[address,4];
4916
4917 Register base_reg;
4918 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4919
4920 EmulateInstruction::Context context;
4921 context.type = eContextRegisterLoad;
4922 context.SetRegisterPlusOffset (base_reg, address - base_address);
4923
4924 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4925 if (!success)
4926 return false;
4927
4928 // if wback then R[n] = offset_addr;
4929 if (wback)
4930 {
4931 context.type = eContextAdjustBaseRegister;
4932 context.SetAddress (offset_addr);
4933 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4934 return false;
4935 }
4936
4937 // if t == 15 then
4938 if (t == 15)
4939 {
4940 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4941 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4942 {
4943 // LoadWritePC (data);
4944 context.type = eContextRegisterLoad;
4945 context.SetRegisterPlusOffset (base_reg, address - base_address);
4946 LoadWritePC (context, data);
4947 }
4948 else
4949 return false;
4950 }
4951 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4952 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4953 {
4954 // R[t] = data;
4955 context.type = eContextRegisterLoad;
4956 context.SetRegisterPlusOffset (base_reg, address - base_address);
4957 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4958 return false;
4959 }
4960 // else // Can only apply before ARMv7
4961 else
4962 {
4963 // R[t] = ROR(data, 8*UInt(address<1:0>));
4964 data = ROR (data, Bits32 (address, 1, 0));
4965 context.type = eContextRegisterLoad;
4966 context.SetImmediate (data);
4967 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4968 return false;
4969 }
4970
4971 }
4972 return true;
4973}
4974
Caroline Ticefe479112011-02-18 18:52:37 +00004975// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4976// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4977bool
4978EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4979{
4980#if 0
4981 if ConditionPassed() then
4982 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4983 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4984 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4985 address = if index then offset_addr else R[n];
4986 data = MemU[address,4];
4987 if wback then R[n] = offset_addr;
4988 if t == 15 then
4989 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4990 elsif UnalignedSupport() || address<1:0> = ’00’ then
4991 R[t] = data;
4992 else // Can only apply before ARMv7
4993 if CurrentInstrSet() == InstrSet_ARM then
4994 R[t] = ROR(data, 8*UInt(address<1:0>));
4995 else
4996 R[t] = bits(32) UNKNOWN;
4997#endif
4998
4999 bool success = false;
5000 const uint32_t opcode = OpcodeAsUnsigned (&success);
5001 if (!success)
5002 return false;
5003
5004 if (ConditionPassed ())
5005 {
5006 const uint32_t addr_byte_size = GetAddressByteSize();
5007
5008 uint32_t t;
5009 uint32_t n;
5010 uint32_t m;
5011 bool index;
5012 bool add;
5013 bool wback;
5014 ARM_ShifterType shift_t;
5015 uint32_t shift_n;
5016
5017 switch (encoding)
5018 {
5019 case eEncodingT1:
5020 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5021 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5022 t = Bits32 (opcode, 2, 0);
5023 n = Bits32 (opcode, 5, 3);
5024 m = Bits32 (opcode, 8, 6);
5025
5026 // index = TRUE; add = TRUE; wback = FALSE;
5027 index = true;
5028 add = true;
5029 wback = false;
5030
5031 // (shift_t, shift_n) = (SRType_LSL, 0);
5032 shift_t = SRType_LSL;
5033 shift_n = 0;
5034
5035 break;
5036
5037 case eEncodingT2:
5038 // if Rn == ’1111’ then SEE LDR (literal);
5039 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5040 t = Bits32 (opcode, 15, 12);
5041 n = Bits32 (opcode, 19, 16);
5042 m = Bits32 (opcode, 3, 0);
5043
5044 // index = TRUE; add = TRUE; wback = FALSE;
5045 index = true;
5046 add = true;
5047 wback = false;
5048
5049 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5050 shift_t = SRType_LSL;
5051 shift_n = Bits32 (opcode, 5, 4);
5052
5053 // if BadReg(m) then UNPREDICTABLE;
5054 if (BadReg (m))
5055 return false;
5056
5057 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5058 if ((t == 15) && InITBlock() && !LastInITBlock())
5059 return false;
5060
5061 break;
5062
5063 case eEncodingA1:
5064 {
5065 // if P == ’0’ && W == ’1’ then SEE LDRT;
5066 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5067 t = Bits32 (opcode, 15, 12);
5068 n = Bits32 (opcode, 19, 16);
5069 m = Bits32 (opcode, 3, 0);
5070
5071 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5072 index = BitIsSet (opcode, 24);
5073 add = BitIsSet (opcode, 23);
5074 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5075
5076 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5077 uint32_t type = Bits32 (opcode, 6, 5);
5078 uint32_t imm5 = Bits32 (opcode, 11, 7);
5079 shift_n = DecodeImmShift (type, imm5, shift_t);
5080
5081 // if m == 15 then UNPREDICTABLE;
5082 if (m == 15)
5083 return false;
5084
5085 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5086 if (wback && ((n == 15) || (n == t)))
5087 return false;
5088 }
5089 break;
5090
5091
5092 default:
5093 return false;
5094 }
5095
5096 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5097 if (!success)
5098 return false;
5099
5100 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5101 if (!success)
5102 return false;
5103
5104 addr_t offset_addr;
5105 addr_t address;
5106
5107 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chen90e607b2011-02-23 00:07:09 +00005108 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005109
5110 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5111 if (add)
5112 offset_addr = Rn + offset;
5113 else
5114 offset_addr = Rn - offset;
5115
5116 // address = if index then offset_addr else R[n];
5117 if (index)
5118 address = offset_addr;
5119 else
5120 address = Rn;
5121
5122 // data = MemU[address,4];
5123 Register base_reg;
5124 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5125
5126 EmulateInstruction::Context context;
5127 context.type = eContextRegisterLoad;
5128 context.SetRegisterPlusOffset (base_reg, address - Rn);
5129
5130 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5131 if (!success)
5132 return false;
5133
5134 // if wback then R[n] = offset_addr;
5135 if (wback)
5136 {
5137 context.type = eContextAdjustBaseRegister;
5138 context.SetAddress (offset_addr);
5139 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5140 return false;
5141 }
5142
5143 // if t == 15 then
5144 if (t == 15)
5145 {
5146 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5147 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5148 {
5149 context.type = eContextRegisterLoad;
5150 context.SetRegisterPlusOffset (base_reg, address - Rn);
5151 LoadWritePC (context, data);
5152 }
5153 else
5154 return false;
5155 }
5156 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5157 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5158 {
5159 // R[t] = data;
5160 context.type = eContextRegisterLoad;
5161 context.SetRegisterPlusOffset (base_reg, address - Rn);
5162 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5163 return false;
5164 }
5165 else // Can only apply before ARMv7
5166 {
5167 // if CurrentInstrSet() == InstrSet_ARM then
5168 if (CurrentInstrSet () == eModeARM)
5169 {
5170 // R[t] = ROR(data, 8*UInt(address<1:0>));
5171 data = ROR (data, Bits32 (address, 1, 0));
5172 context.type = eContextRegisterLoad;
5173 context.SetImmediate (data);
5174 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5175 return false;
5176 }
5177 else
5178 {
5179 // R[t] = bits(32) UNKNOWN;
5180 WriteBits32Unknown (t);
5181 }
5182 }
5183 }
5184 return true;
5185}
Caroline Tice21b604b2011-02-18 21:06:04 +00005186
5187// LDRB (immediate, Thumb)
5188bool
5189EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5190{
5191#if 0
5192 if ConditionPassed() then
5193 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5194 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5195 address = if index then offset_addr else R[n];
5196 R[t] = ZeroExtend(MemU[address,1], 32);
5197 if wback then R[n] = offset_addr;
5198#endif
5199
5200 bool success = false;
5201 const uint32_t opcode = OpcodeAsUnsigned (&success);
5202 if (!success)
5203 return false;
5204
5205 if (ConditionPassed ())
5206 {
5207 uint32_t t;
5208 uint32_t n;
5209 uint32_t imm32;
5210 bool index;
5211 bool add;
5212 bool wback;
5213
5214 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5215 switch (encoding)
5216 {
5217 case eEncodingT1:
5218 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5219 t = Bits32 (opcode, 2, 0);
5220 n = Bits32 (opcode, 5, 3);
5221 imm32 = Bits32 (opcode, 10, 6);
5222
5223 // index = TRUE; add = TRUE; wback = FALSE;
5224 index = true;
5225 add = true;
5226 wback= false;
5227
5228 break;
5229
5230 case eEncodingT2:
5231 // if Rt == ’1111’ then SEE PLD;
5232 // if Rn == ’1111’ then SEE LDRB (literal);
5233 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5234 t = Bits32 (opcode, 15, 12);
5235 n = Bits32 (opcode, 19, 16);
5236 imm32 = Bits32 (opcode, 11, 0);
5237
5238 // index = TRUE; add = TRUE; wback = FALSE;
5239 index = true;
5240 add = true;
5241 wback = false;
5242
5243 // if t == 13 then UNPREDICTABLE;
5244 if (t == 13)
5245 return false;
5246
5247 break;
5248
5249 case eEncodingT3:
5250 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5251 // if Rn == ’1111’ then SEE LDRB (literal);
5252 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5253 // if P == ’0’ && W == ’0’ then UNDEFINED;
5254 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5255 return false;
5256
5257 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5258 t = Bits32 (opcode, 15, 12);
5259 n = Bits32 (opcode, 19, 16);
5260 imm32 = Bits32 (opcode, 7, 0);
5261
5262 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5263 index = BitIsSet (opcode, 10);
5264 add = BitIsSet (opcode, 9);
5265 wback = BitIsSet (opcode, 8);
5266
5267 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5268 if (BadReg (t) || (wback && (n == t)))
5269 return false;
5270
5271 break;
5272
5273 default:
5274 return false;
5275 }
5276
5277 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5278 if (!success)
5279 return false;
5280
5281 addr_t address;
5282 addr_t offset_addr;
5283
5284 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5285 if (add)
5286 offset_addr = Rn + imm32;
5287 else
5288 offset_addr = Rn - imm32;
5289
5290 // address = if index then offset_addr else R[n];
5291 if (index)
5292 address = offset_addr;
5293 else
5294 address = Rn;
5295
5296 // R[t] = ZeroExtend(MemU[address,1], 32);
5297 Register base_reg;
5298 Register data_reg;
5299 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5300 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5301
5302 EmulateInstruction::Context context;
5303 context.type = eContextRegisterLoad;
5304 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5305
5306 uint64_t data = MemURead (context, address, 1, 0, &success);
5307 if (!success)
5308 return false;
5309
5310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5311 return false;
5312
5313 // if wback then R[n] = offset_addr;
5314 if (wback)
5315 {
5316 context.type = eContextAdjustBaseRegister;
5317 context.SetAddress (offset_addr);
5318 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5319 return false;
5320 }
5321 }
5322 return true;
5323}
Caroline Ticef55261f2011-02-18 22:24:22 +00005324
5325// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5326// zero-extends it to form a 32-bit word and writes it to a register.
5327bool
5328EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5329{
5330#if 0
5331 if ConditionPassed() then
5332 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5333 base = Align(PC,4);
5334 address = if add then (base + imm32) else (base - imm32);
5335 R[t] = ZeroExtend(MemU[address,1], 32);
5336#endif
5337
5338 bool success = false;
5339 const uint32_t opcode = OpcodeAsUnsigned (&success);
5340 if (!success)
5341 return false;
5342
5343 if (ConditionPassed ())
5344 {
5345 uint32_t t;
5346 uint32_t imm32;
5347 bool add;
5348 switch (encoding)
5349 {
5350 case eEncodingT1:
5351 // if Rt == ’1111’ then SEE PLD;
5352 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5353 t = Bits32 (opcode, 15, 12);
5354 imm32 = Bits32 (opcode, 11, 0);
5355 add = BitIsSet (opcode, 23);
5356
5357 // if t == 13 then UNPREDICTABLE;
5358 if (t == 13)
5359 return false;
5360
5361 break;
5362
5363 case eEncodingA1:
5364 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5365 t = Bits32 (opcode, 15, 12);
5366 imm32 = Bits32 (opcode, 11, 0);
5367 add = BitIsSet (opcode, 23);
5368
5369 // if t == 15 then UNPREDICTABLE;
5370 if (t == 15)
5371 return false;
5372 break;
5373
5374 default:
5375 return false;
5376 }
5377
5378 // base = Align(PC,4);
5379 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5380 if (!success)
5381 return false;
5382
5383 uint32_t base = AlignPC (pc_val);
5384
5385 addr_t address;
5386 // address = if add then (base + imm32) else (base - imm32);
5387 if (add)
5388 address = base + imm32;
5389 else
5390 address = base - imm32;
5391
5392 // R[t] = ZeroExtend(MemU[address,1], 32);
5393 EmulateInstruction::Context context;
5394 context.type = eContextRelativeBranchImmediate;
5395 context.SetImmediate (address - base);
5396
5397 uint64_t data = MemURead (context, address, 1, 0, &success);
5398 if (!success)
5399 return false;
5400
5401 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5402 return false;
5403 }
5404 return true;
5405}
Caroline Tice30fec122011-02-18 23:52:21 +00005406
5407// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5408// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5409// optionally be shifted.
5410bool
5411EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5412{
5413#if 0
5414 if ConditionPassed() then
5415 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5416 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5417 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5418 address = if index then offset_addr else R[n];
5419 R[t] = ZeroExtend(MemU[address,1],32);
5420 if wback then R[n] = offset_addr;
5421#endif
5422
5423 bool success = false;
5424 const uint32_t opcode = OpcodeAsUnsigned (&success);
5425 if (!success)
5426 return false;
5427
5428 if (ConditionPassed ())
5429 {
5430 uint32_t t;
5431 uint32_t n;
5432 uint32_t m;
5433 bool index;
5434 bool add;
5435 bool wback;
5436 ARM_ShifterType shift_t;
5437 uint32_t shift_n;
5438
5439 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5440 switch (encoding)
5441 {
5442 case eEncodingT1:
5443 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5444 t = Bits32 (opcode, 2, 0);
5445 n = Bits32 (opcode, 5, 3);
5446 m = Bits32 (opcode, 8, 6);
5447
5448 // index = TRUE; add = TRUE; wback = FALSE;
5449 index = true;
5450 add = true;
5451 wback = false;
5452
5453 // (shift_t, shift_n) = (SRType_LSL, 0);
5454 shift_t = SRType_LSL;
5455 shift_n = 0;
5456 break;
5457
5458 case eEncodingT2:
5459 // if Rt == ’1111’ then SEE PLD;
5460 // if Rn == ’1111’ then SEE LDRB (literal);
5461 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5462 t = Bits32 (opcode, 15, 12);
5463 n = Bits32 (opcode, 19, 16);
5464 m = Bits32 (opcode, 3, 0);
5465
5466 // index = TRUE; add = TRUE; wback = FALSE;
5467 index = true;
5468 add = true;
5469 wback = false;
5470
5471 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5472 shift_t = SRType_LSL;
5473 shift_n = Bits32 (opcode, 5, 4);
5474
5475 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5476 if ((t == 13) || BadReg (m))
5477 return false;
5478 break;
5479
5480 case eEncodingA1:
5481 {
5482 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5483 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5484 t = Bits32 (opcode, 15, 12);
5485 n = Bits32 (opcode, 19, 16);
5486 m = Bits32 (opcode, 3, 0);
5487
5488 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5489 index = BitIsSet (opcode, 24);
5490 add = BitIsSet (opcode, 23);
5491 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5492
5493 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5494 uint32_t type = Bits32 (opcode, 6, 5);
5495 uint32_t imm5 = Bits32 (opcode, 11, 7);
5496 shift_n = DecodeImmShift (type, imm5, shift_t);
5497
5498 // if t == 15 || m == 15 then UNPREDICTABLE;
5499 if ((t == 15) || (m == 15))
5500 return false;
5501
5502 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5503 if (wback && ((n == 15) || (n == t)))
5504 return false;
5505 }
5506 break;
5507
5508 default:
5509 return false;
5510 }
5511
5512 addr_t offset_addr;
5513 addr_t address;
5514
5515 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5516 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5517 if (!success)
5518 return false;
5519
5520 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5521
5522 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5523 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5524 if (!success)
5525 return false;
5526
5527 if (add)
5528 offset_addr = Rn + offset;
5529 else
5530 offset_addr = Rn - offset;
5531
5532 // address = if index then offset_addr else R[n];
5533 if (index)
5534 address = offset_addr;
5535 else
5536 address = Rn;
5537
5538 // R[t] = ZeroExtend(MemU[address,1],32);
5539 Register base_reg;
5540 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5541
5542 EmulateInstruction::Context context;
5543 context.type = eContextRegisterLoad;
5544 context.SetRegisterPlusOffset (base_reg, address - Rn);
5545
5546 uint64_t data = MemURead (context, address, 1, 0, &success);
5547 if (!success)
5548 return false;
5549
5550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5551 return false;
5552
5553 // if wback then R[n] = offset_addr;
5554 if (wback)
5555 {
5556 context.type = eContextAdjustBaseRegister;
5557 context.SetAddress (offset_addr);
5558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5559 return false;
5560 }
5561 }
5562 return true;
5563}
Caroline Ticefe479112011-02-18 18:52:37 +00005564
Johnny Chen2115b412011-02-21 23:42:44 +00005565// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5566// and writes the result to the destination register. It can optionally update the condition flags based on
5567// the result.
5568bool
5569EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5570{
5571#if 0
5572 // ARM pseudo code...
5573 if ConditionPassed() then
5574 EncodingSpecificOperations();
5575 result = R[n] EOR imm32;
5576 if d == 15 then // Can only occur for ARM encoding
5577 ALUWritePC(result); // setflags is always FALSE here
5578 else
5579 R[d] = result;
5580 if setflags then
5581 APSR.N = result<31>;
5582 APSR.Z = IsZeroBit(result);
5583 APSR.C = carry;
5584 // APSR.V unchanged
5585#endif
5586
5587 bool success = false;
5588 const uint32_t opcode = OpcodeAsUnsigned (&success);
5589 if (!success)
5590 return false;
5591
5592 if (ConditionPassed())
5593 {
5594 uint32_t Rd, Rn;
5595 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5596 bool setflags;
5597 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5598 switch (encoding)
5599 {
5600 case eEncodingT1:
5601 Rd = Bits32(opcode, 11, 8);
5602 Rn = Bits32(opcode, 19, 16);
5603 setflags = BitIsSet(opcode, 20);
5604 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5605 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5606 if (Rd == 15 && setflags)
5607 return EmulateTEQImm(eEncodingT1);
5608 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5609 return false;
5610 break;
5611 case eEncodingA1:
5612 Rd = Bits32(opcode, 15, 12);
5613 Rn = Bits32(opcode, 19, 16);
5614 setflags = BitIsSet(opcode, 20);
5615 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5616 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5617 // TODO: Emulate SUBS PC, LR and related instructions.
5618 if (Rd == 15 && setflags)
5619 return false;
5620 break;
5621 default:
5622 return false;
5623 }
5624
5625 // Read the first operand.
5626 uint32_t val1 = ReadCoreReg(Rn, &success);
5627 if (!success)
5628 return false;
5629
5630 uint32_t result = val1 ^ imm32;
5631
5632 EmulateInstruction::Context context;
5633 context.type = EmulateInstruction::eContextImmediate;
5634 context.SetNoArgs ();
5635
5636 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5637 return false;
5638 }
5639 return true;
5640}
5641
5642// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5643// optionally-shifted register value, and writes the result to the destination register.
5644// It can optionally update the condition flags based on the result.
5645bool
5646EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5647{
5648#if 0
5649 // ARM pseudo code...
5650 if ConditionPassed() then
5651 EncodingSpecificOperations();
5652 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5653 result = R[n] EOR shifted;
5654 if d == 15 then // Can only occur for ARM encoding
5655 ALUWritePC(result); // setflags is always FALSE here
5656 else
5657 R[d] = result;
5658 if setflags then
5659 APSR.N = result<31>;
5660 APSR.Z = IsZeroBit(result);
5661 APSR.C = carry;
5662 // APSR.V unchanged
5663#endif
5664
5665 bool success = false;
5666 const uint32_t opcode = OpcodeAsUnsigned (&success);
5667 if (!success)
5668 return false;
5669
5670 if (ConditionPassed())
5671 {
5672 uint32_t Rd, Rn, Rm;
5673 ARM_ShifterType shift_t;
5674 uint32_t shift_n; // the shift applied to the value read from Rm
5675 bool setflags;
5676 uint32_t carry;
5677 switch (encoding)
5678 {
5679 case eEncodingT1:
5680 Rd = Rn = Bits32(opcode, 2, 0);
5681 Rm = Bits32(opcode, 5, 3);
5682 setflags = !InITBlock();
5683 shift_t = SRType_LSL;
5684 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005685 break;
Johnny Chen2115b412011-02-21 23:42:44 +00005686 case eEncodingT2:
5687 Rd = Bits32(opcode, 11, 8);
5688 Rn = Bits32(opcode, 19, 16);
5689 Rm = Bits32(opcode, 3, 0);
5690 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005691 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5692 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005693 if (Rd == 15 && setflags)
5694 return EmulateTEQReg(eEncodingT1);
5695 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5696 return false;
5697 break;
5698 case eEncodingA1:
5699 Rd = Bits32(opcode, 15, 12);
5700 Rn = Bits32(opcode, 19, 16);
5701 Rm = Bits32(opcode, 3, 0);
5702 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005703 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005704 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5705 // TODO: Emulate SUBS PC, LR and related instructions.
5706 if (Rd == 15 && setflags)
5707 return false;
5708 break;
5709 default:
5710 return false;
5711 }
5712
5713 // Read the first operand.
5714 uint32_t val1 = ReadCoreReg(Rn, &success);
5715 if (!success)
5716 return false;
5717
5718 // Read the second operand.
5719 uint32_t val2 = ReadCoreReg(Rm, &success);
5720 if (!success)
5721 return false;
5722
5723 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5724 uint32_t result = val1 ^ shifted;
5725
5726 EmulateInstruction::Context context;
5727 context.type = EmulateInstruction::eContextImmediate;
5728 context.SetNoArgs ();
5729
5730 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5731 return false;
5732 }
5733 return true;
5734}
5735
Johnny Chen7c5234d2011-02-18 23:41:11 +00005736// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5737// writes the result to the destination register. It can optionally update the condition flags based
5738// on the result.
5739bool
5740EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5741{
5742#if 0
5743 // ARM pseudo code...
5744 if ConditionPassed() then
5745 EncodingSpecificOperations();
5746 result = R[n] OR imm32;
5747 if d == 15 then // Can only occur for ARM encoding
5748 ALUWritePC(result); // setflags is always FALSE here
5749 else
5750 R[d] = result;
5751 if setflags then
5752 APSR.N = result<31>;
5753 APSR.Z = IsZeroBit(result);
5754 APSR.C = carry;
5755 // APSR.V unchanged
5756#endif
5757
5758 bool success = false;
5759 const uint32_t opcode = OpcodeAsUnsigned (&success);
5760 if (!success)
5761 return false;
5762
5763 if (ConditionPassed())
5764 {
5765 uint32_t Rd, Rn;
5766 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5767 bool setflags;
5768 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5769 switch (encoding)
5770 {
5771 case eEncodingT1:
5772 Rd = Bits32(opcode, 11, 8);
5773 Rn = Bits32(opcode, 19, 16);
5774 setflags = BitIsSet(opcode, 20);
5775 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5776 // if Rn == ‘1111’ then SEE MOV (immediate);
5777 if (Rn == 15)
5778 return EmulateMOVRdImm(eEncodingT2);
5779 if (BadReg(Rd) || Rn == 13)
5780 return false;
5781 break;
5782 case eEncodingA1:
5783 Rd = Bits32(opcode, 15, 12);
5784 Rn = Bits32(opcode, 19, 16);
5785 setflags = BitIsSet(opcode, 20);
5786 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5787 // TODO: Emulate SUBS PC, LR and related instructions.
5788 if (Rd == 15 && setflags)
5789 return false;
5790 break;
5791 default:
5792 return false;
5793 }
5794
5795 // Read the first operand.
5796 uint32_t val1 = ReadCoreReg(Rn, &success);
5797 if (!success)
5798 return false;
5799
5800 uint32_t result = val1 | imm32;
5801
5802 EmulateInstruction::Context context;
5803 context.type = EmulateInstruction::eContextImmediate;
5804 context.SetNoArgs ();
5805
5806 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5807 return false;
5808 }
5809 return true;
5810}
5811
5812// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5813// value, and writes the result to the destination register. It can optionally update the condition flags based
5814// on the result.
5815bool
5816EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5817{
5818#if 0
5819 // ARM pseudo code...
5820 if ConditionPassed() then
5821 EncodingSpecificOperations();
5822 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5823 result = R[n] OR shifted;
5824 if d == 15 then // Can only occur for ARM encoding
5825 ALUWritePC(result); // setflags is always FALSE here
5826 else
5827 R[d] = result;
5828 if setflags then
5829 APSR.N = result<31>;
5830 APSR.Z = IsZeroBit(result);
5831 APSR.C = carry;
5832 // APSR.V unchanged
5833#endif
5834
5835 bool success = false;
5836 const uint32_t opcode = OpcodeAsUnsigned (&success);
5837 if (!success)
5838 return false;
5839
5840 if (ConditionPassed())
5841 {
5842 uint32_t Rd, Rn, Rm;
5843 ARM_ShifterType shift_t;
5844 uint32_t shift_n; // the shift applied to the value read from Rm
5845 bool setflags;
5846 uint32_t carry;
5847 switch (encoding)
5848 {
5849 case eEncodingT1:
5850 Rd = Rn = Bits32(opcode, 2, 0);
5851 Rm = Bits32(opcode, 5, 3);
5852 setflags = !InITBlock();
5853 shift_t = SRType_LSL;
5854 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005855 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005856 case eEncodingT2:
5857 Rd = Bits32(opcode, 11, 8);
5858 Rn = Bits32(opcode, 19, 16);
5859 Rm = Bits32(opcode, 3, 0);
5860 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005861 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5862 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005863 if (Rn == 15)
5864 return EmulateMOVRdRm(eEncodingT3);
5865 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5866 return false;
5867 break;
5868 case eEncodingA1:
5869 Rd = Bits32(opcode, 15, 12);
5870 Rn = Bits32(opcode, 19, 16);
5871 Rm = Bits32(opcode, 3, 0);
5872 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005873 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005874 // TODO: Emulate SUBS PC, LR and related instructions.
5875 if (Rd == 15 && setflags)
5876 return false;
5877 break;
5878 default:
5879 return false;
5880 }
5881
5882 // Read the first operand.
5883 uint32_t val1 = ReadCoreReg(Rn, &success);
5884 if (!success)
5885 return false;
5886
5887 // Read the second operand.
5888 uint32_t val2 = ReadCoreReg(Rm, &success);
5889 if (!success)
5890 return false;
5891
5892 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005893 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005894
5895 EmulateInstruction::Context context;
5896 context.type = EmulateInstruction::eContextImmediate;
5897 context.SetNoArgs ();
5898
5899 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5900 return false;
5901 }
5902 return true;
5903}
5904
Johnny Chened32e7c2011-02-22 23:42:58 +00005905// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
5906// the destination register. It can optionally update the condition flags based on the result.
5907bool
5908EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
5909{
5910#if 0
5911 // ARM pseudo code...
5912 if ConditionPassed() then
5913 EncodingSpecificOperations();
5914 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
5915 if d == 15 then // Can only occur for ARM encoding
5916 ALUWritePC(result); // setflags is always FALSE here
5917 else
5918 R[d] = result;
5919 if setflags then
5920 APSR.N = result<31>;
5921 APSR.Z = IsZeroBit(result);
5922 APSR.C = carry;
5923 APSR.V = overflow;
5924#endif
5925
5926 bool success = false;
5927 const uint32_t opcode = OpcodeAsUnsigned (&success);
5928 if (!success)
5929 return false;
5930
5931 uint32_t Rd; // the destination register
5932 uint32_t Rn; // the first operand
5933 bool setflags;
5934 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5935 switch (encoding) {
5936 case eEncodingT1:
5937 Rd = Bits32(opcode, 2, 0);
5938 Rn = Bits32(opcode, 5, 3);
5939 setflags = !InITBlock();
5940 imm32 = 0;
5941 break;
5942 case eEncodingT2:
5943 Rd = Bits32(opcode, 11, 8);
5944 Rn = Bits32(opcode, 19, 16);
5945 setflags = BitIsSet(opcode, 20);
5946 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5947 if (BadReg(Rd) || BadReg(Rn))
5948 return false;
5949 break;
5950 case eEncodingA1:
5951 Rd = Bits32(opcode, 15, 12);
5952 Rn = Bits32(opcode, 19, 16);
5953 setflags = BitIsSet(opcode, 20);
5954 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5955 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5956 // TODO: Emulate SUBS PC, LR and related instructions.
5957 if (Rd == 15 && setflags)
5958 return false;
5959 break;
5960 default:
5961 return false;
5962 }
5963 // Read the register value from the operand register Rn.
5964 uint32_t reg_val = ReadCoreReg(Rn, &success);
5965 if (!success)
5966 return false;
5967
5968 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
5969
5970 EmulateInstruction::Context context;
5971 context.type = EmulateInstruction::eContextImmediate;
5972 context.SetNoArgs ();
5973
5974 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5975 return false;
5976
5977 return true;
5978}
5979
5980// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
5981// result to the destination register. It can optionally update the condition flags based on the result.
5982bool
5983EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
5984{
5985#if 0
5986 // ARM pseudo code...
5987 if ConditionPassed() then
5988 EncodingSpecificOperations();
5989 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5990 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
5991 if d == 15 then // Can only occur for ARM encoding
5992 ALUWritePC(result); // setflags is always FALSE here
5993 else
5994 R[d] = result;
5995 if setflags then
5996 APSR.N = result<31>;
5997 APSR.Z = IsZeroBit(result);
5998 APSR.C = carry;
5999 APSR.V = overflow;
6000#endif
6001
6002 bool success = false;
6003 const uint32_t opcode = OpcodeAsUnsigned (&success);
6004 if (!success)
6005 return false;
6006
6007 uint32_t Rd; // the destination register
6008 uint32_t Rn; // the first operand
6009 uint32_t Rm; // the second operand
6010 bool setflags;
6011 ARM_ShifterType shift_t;
6012 uint32_t shift_n; // the shift applied to the value read from Rm
6013 switch (encoding) {
6014 case eEncodingT1:
6015 Rd = Bits32(opcode, 11, 8);
6016 Rn = Bits32(opcode, 19, 16);
6017 Rm = Bits32(opcode, 3, 0);
6018 setflags = BitIsSet(opcode, 20);
6019 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6020 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6021 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6022 return false;
6023 break;
6024 case eEncodingA1:
6025 Rd = Bits32(opcode, 15, 12);
6026 Rn = Bits32(opcode, 19, 16);
6027 Rm = Bits32(opcode, 3, 0);
6028 setflags = BitIsSet(opcode, 20);
6029 shift_n = DecodeImmShiftARM(opcode, shift_t);
6030 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6031 // TODO: Emulate SUBS PC, LR and related instructions.
6032 if (Rd == 15 && setflags)
6033 return false;
6034 break;
6035 default:
6036 return false;
6037 }
6038 // Read the register value from register Rn.
6039 uint32_t val1 = ReadCoreReg(Rn, &success);
6040 if (!success)
6041 return false;
6042
6043 // Read the register value from register Rm.
6044 uint32_t val2 = ReadCoreReg(Rm, &success);
6045 if (!success)
6046 return false;
6047
6048 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6049 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6050
6051 EmulateInstruction::Context context;
6052 context.type = EmulateInstruction::eContextImmediate;
6053 context.SetNoArgs();
6054 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6055 return false;
6056
6057 return true;
6058}
6059
Johnny Chen90e607b2011-02-23 00:07:09 +00006060// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
6061// an immediate value, and writes the result to the destination register. It can optionally update the condition
6062// flags based on the result.
6063bool
6064EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
6065{
6066#if 0
6067 // ARM pseudo code...
6068 if ConditionPassed() then
6069 EncodingSpecificOperations();
6070 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
6071 if d == 15 then
6072 ALUWritePC(result); // setflags is always FALSE here
6073 else
6074 R[d] = result;
6075 if setflags then
6076 APSR.N = result<31>;
6077 APSR.Z = IsZeroBit(result);
6078 APSR.C = carry;
6079 APSR.V = overflow;
6080#endif
6081
6082 bool success = false;
6083 const uint32_t opcode = OpcodeAsUnsigned (&success);
6084 if (!success)
6085 return false;
6086
6087 uint32_t Rd; // the destination register
6088 uint32_t Rn; // the first operand
6089 bool setflags;
6090 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6091 switch (encoding) {
6092 case eEncodingA1:
6093 Rd = Bits32(opcode, 15, 12);
6094 Rn = Bits32(opcode, 19, 16);
6095 setflags = BitIsSet(opcode, 20);
6096 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6097 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6098 // TODO: Emulate SUBS PC, LR and related instructions.
6099 if (Rd == 15 && setflags)
6100 return false;
6101 break;
6102 default:
6103 return false;
6104 }
6105 // Read the register value from the operand register Rn.
6106 uint32_t reg_val = ReadCoreReg(Rn, &success);
6107 if (!success)
6108 return false;
6109
6110 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
6111
6112 EmulateInstruction::Context context;
6113 context.type = EmulateInstruction::eContextImmediate;
6114 context.SetNoArgs ();
6115
6116 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6117 return false;
6118
6119 return true;
6120}
6121
6122// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
6123// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
6124// condition flags based on the result.
6125bool
6126EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
6127{
6128#if 0
6129 // ARM pseudo code...
6130 if ConditionPassed() then
6131 EncodingSpecificOperations();
6132 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6133 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
6134 if d == 15 then
6135 ALUWritePC(result); // setflags is always FALSE here
6136 else
6137 R[d] = result;
6138 if setflags then
6139 APSR.N = result<31>;
6140 APSR.Z = IsZeroBit(result);
6141 APSR.C = carry;
6142 APSR.V = overflow;
6143#endif
6144
6145 bool success = false;
6146 const uint32_t opcode = OpcodeAsUnsigned (&success);
6147 if (!success)
6148 return false;
6149
6150 uint32_t Rd; // the destination register
6151 uint32_t Rn; // the first operand
6152 uint32_t Rm; // the second operand
6153 bool setflags;
6154 ARM_ShifterType shift_t;
6155 uint32_t shift_n; // the shift applied to the value read from Rm
6156 switch (encoding) {
6157 case eEncodingA1:
6158 Rd = Bits32(opcode, 15, 12);
6159 Rn = Bits32(opcode, 19, 16);
6160 Rm = Bits32(opcode, 3, 0);
6161 setflags = BitIsSet(opcode, 20);
6162 shift_n = DecodeImmShiftARM(opcode, shift_t);
6163 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6164 // TODO: Emulate SUBS PC, LR and related instructions.
6165 if (Rd == 15 && setflags)
6166 return false;
6167 break;
6168 default:
6169 return false;
6170 }
6171 // Read the register value from register Rn.
6172 uint32_t val1 = ReadCoreReg(Rn, &success);
6173 if (!success)
6174 return false;
6175
6176 // Read the register value from register Rm.
6177 uint32_t val2 = ReadCoreReg(Rm, &success);
6178 if (!success)
6179 return false;
6180
6181 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6182 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
6183
6184 EmulateInstruction::Context context;
6185 context.type = EmulateInstruction::eContextImmediate;
6186 context.SetNoArgs();
6187 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6188 return false;
6189
6190 return true;
6191}
6192
Johnny Chen9b381772011-02-23 01:01:21 +00006193// Subtract with Carry (immediate) subtracts an immediate value and the value of
6194// NOT (Carry flag) from a register value, and writes the result to the destination register.
6195// It can optionally update the condition flags based on the result.
6196bool
6197EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
6198{
6199#if 0
6200 // ARM pseudo code...
6201 if ConditionPassed() then
6202 EncodingSpecificOperations();
6203 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
6204 if d == 15 then // Can only occur for ARM encoding
6205 ALUWritePC(result); // setflags is always FALSE here
6206 else
6207 R[d] = result;
6208 if setflags then
6209 APSR.N = result<31>;
6210 APSR.Z = IsZeroBit(result);
6211 APSR.C = carry;
6212 APSR.V = overflow;
6213#endif
6214
6215 bool success = false;
6216 const uint32_t opcode = OpcodeAsUnsigned (&success);
6217 if (!success)
6218 return false;
6219
6220 uint32_t Rd; // the destination register
6221 uint32_t Rn; // the first operand
6222 bool setflags;
6223 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6224 switch (encoding) {
6225 case eEncodingT1:
6226 Rd = Bits32(opcode, 11, 8);
6227 Rn = Bits32(opcode, 19, 16);
6228 setflags = BitIsSet(opcode, 20);
6229 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6230 if (BadReg(Rd) || BadReg(Rn))
6231 return false;
6232 break;
6233 case eEncodingA1:
6234 Rd = Bits32(opcode, 15, 12);
6235 Rn = Bits32(opcode, 19, 16);
6236 setflags = BitIsSet(opcode, 20);
6237 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6238 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6239 // TODO: Emulate SUBS PC, LR and related instructions.
6240 if (Rd == 15 && setflags)
6241 return false;
6242 break;
6243 default:
6244 return false;
6245 }
6246 // Read the register value from the operand register Rn.
6247 uint32_t reg_val = ReadCoreReg(Rn, &success);
6248 if (!success)
6249 return false;
6250
6251 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
6252
6253 EmulateInstruction::Context context;
6254 context.type = EmulateInstruction::eContextImmediate;
6255 context.SetNoArgs ();
6256
6257 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6258 return false;
6259
6260 return true;
6261}
6262
6263// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
6264// NOT (Carry flag) from a register value, and writes the result to the destination register.
6265// It can optionally update the condition flags based on the result.
6266bool
6267EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
6268{
6269#if 0
6270 // ARM pseudo code...
6271 if ConditionPassed() then
6272 EncodingSpecificOperations();
6273 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6274 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
6275 if d == 15 then // Can only occur for ARM encoding
6276 ALUWritePC(result); // setflags is always FALSE here
6277 else
6278 R[d] = result;
6279 if setflags then
6280 APSR.N = result<31>;
6281 APSR.Z = IsZeroBit(result);
6282 APSR.C = carry;
6283 APSR.V = overflow;
6284#endif
6285
6286 bool success = false;
6287 const uint32_t opcode = OpcodeAsUnsigned (&success);
6288 if (!success)
6289 return false;
6290
6291 uint32_t Rd; // the destination register
6292 uint32_t Rn; // the first operand
6293 uint32_t Rm; // the second operand
6294 bool setflags;
6295 ARM_ShifterType shift_t;
6296 uint32_t shift_n; // the shift applied to the value read from Rm
6297 switch (encoding) {
6298 case eEncodingT1:
6299 Rd = Rn = Bits32(opcode, 2, 0);
6300 Rm = Bits32(opcode, 5, 3);
6301 setflags = !InITBlock();
6302 shift_t = SRType_LSL;
6303 shift_n = 0;
6304 break;
6305 case eEncodingT2:
6306 Rd = Bits32(opcode, 11, 8);
6307 Rn = Bits32(opcode, 19, 16);
6308 Rm = Bits32(opcode, 3, 0);
6309 setflags = BitIsSet(opcode, 20);
6310 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6311 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6312 return false;
6313 break;
6314 case eEncodingA1:
6315 Rd = Bits32(opcode, 15, 12);
6316 Rn = Bits32(opcode, 19, 16);
6317 Rm = Bits32(opcode, 3, 0);
6318 setflags = BitIsSet(opcode, 20);
6319 shift_n = DecodeImmShiftARM(opcode, shift_t);
6320 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6321 // TODO: Emulate SUBS PC, LR and related instructions.
6322 if (Rd == 15 && setflags)
6323 return false;
6324 break;
6325 default:
6326 return false;
6327 }
6328 // Read the register value from register Rn.
6329 uint32_t val1 = ReadCoreReg(Rn, &success);
6330 if (!success)
6331 return false;
6332
6333 // Read the register value from register Rm.
6334 uint32_t val2 = ReadCoreReg(Rm, &success);
6335 if (!success)
6336 return false;
6337
6338 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6339 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
6340
6341 EmulateInstruction::Context context;
6342 context.type = EmulateInstruction::eContextImmediate;
6343 context.SetNoArgs();
6344 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6345 return false;
6346
6347 return true;
6348}
6349
Johnny Chen2115b412011-02-21 23:42:44 +00006350// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
6351// immediate value. It updates the condition flags based on the result, and discards the result.
6352bool
6353EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
6354{
6355#if 0
6356 // ARM pseudo code...
6357 if ConditionPassed() then
6358 EncodingSpecificOperations();
6359 result = R[n] EOR imm32;
6360 APSR.N = result<31>;
6361 APSR.Z = IsZeroBit(result);
6362 APSR.C = carry;
6363 // APSR.V unchanged
6364#endif
6365
6366 bool success = false;
6367 const uint32_t opcode = OpcodeAsUnsigned (&success);
6368 if (!success)
6369 return false;
6370
6371 if (ConditionPassed())
6372 {
6373 uint32_t Rn;
6374 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6375 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6376 switch (encoding)
6377 {
6378 case eEncodingT1:
6379 Rn = Bits32(opcode, 19, 16);
6380 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6381 if (BadReg(Rn))
6382 return false;
6383 break;
6384 case eEncodingA1:
6385 Rn = Bits32(opcode, 19, 16);
6386 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6387 break;
6388 default:
6389 return false;
6390 }
6391
6392 // Read the first operand.
6393 uint32_t val1 = ReadCoreReg(Rn, &success);
6394 if (!success)
6395 return false;
6396
6397 uint32_t result = val1 ^ imm32;
6398
6399 EmulateInstruction::Context context;
6400 context.type = EmulateInstruction::eContextImmediate;
6401 context.SetNoArgs ();
6402
6403 if (!WriteFlags(context, result, carry))
6404 return false;
6405 }
6406 return true;
6407}
6408
6409// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
6410// optionally-shifted register value. It updates the condition flags based on the result, and discards
6411// the result.
6412bool
6413EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
6414{
6415#if 0
6416 // ARM pseudo code...
6417 if ConditionPassed() then
6418 EncodingSpecificOperations();
6419 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6420 result = R[n] EOR shifted;
6421 APSR.N = result<31>;
6422 APSR.Z = IsZeroBit(result);
6423 APSR.C = carry;
6424 // APSR.V unchanged
6425#endif
6426
6427 bool success = false;
6428 const uint32_t opcode = OpcodeAsUnsigned (&success);
6429 if (!success)
6430 return false;
6431
6432 if (ConditionPassed())
6433 {
6434 uint32_t Rn, Rm;
6435 ARM_ShifterType shift_t;
6436 uint32_t shift_n; // the shift applied to the value read from Rm
6437 uint32_t carry;
6438 switch (encoding)
6439 {
6440 case eEncodingT1:
6441 Rn = Bits32(opcode, 19, 16);
6442 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006443 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006444 if (BadReg(Rn) || BadReg(Rm))
6445 return false;
6446 break;
6447 case eEncodingA1:
6448 Rn = Bits32(opcode, 19, 16);
6449 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006450 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006451 break;
6452 default:
6453 return false;
6454 }
6455
6456 // Read the first operand.
6457 uint32_t val1 = ReadCoreReg(Rn, &success);
6458 if (!success)
6459 return false;
6460
6461 // Read the second operand.
6462 uint32_t val2 = ReadCoreReg(Rm, &success);
6463 if (!success)
6464 return false;
6465
6466 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6467 uint32_t result = val1 ^ shifted;
6468
6469 EmulateInstruction::Context context;
6470 context.type = EmulateInstruction::eContextImmediate;
6471 context.SetNoArgs ();
6472
6473 if (!WriteFlags(context, result, carry))
6474 return false;
6475 }
6476 return true;
6477}
6478
Johnny Chende3cce32011-02-21 21:24:49 +00006479// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
6480// It updates the condition flags based on the result, and discards the result.
6481bool
6482EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6483{
6484#if 0
6485 // ARM pseudo code...
6486 if ConditionPassed() then
6487 EncodingSpecificOperations();
6488 result = R[n] AND imm32;
6489 APSR.N = result<31>;
6490 APSR.Z = IsZeroBit(result);
6491 APSR.C = carry;
6492 // APSR.V unchanged
6493#endif
6494
6495 bool success = false;
6496 const uint32_t opcode = OpcodeAsUnsigned (&success);
6497 if (!success)
6498 return false;
6499
6500 if (ConditionPassed())
6501 {
6502 uint32_t Rn;
6503 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6504 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6505 switch (encoding)
6506 {
6507 case eEncodingT1:
6508 Rn = Bits32(opcode, 19, 16);
6509 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6510 if (BadReg(Rn))
6511 return false;
6512 break;
6513 case eEncodingA1:
6514 Rn = Bits32(opcode, 19, 16);
6515 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6516 break;
6517 default:
6518 return false;
6519 }
6520
6521 // Read the first operand.
6522 uint32_t val1 = ReadCoreReg(Rn, &success);
6523 if (!success)
6524 return false;
6525
6526 uint32_t result = val1 & imm32;
6527
6528 EmulateInstruction::Context context;
6529 context.type = EmulateInstruction::eContextImmediate;
6530 context.SetNoArgs ();
6531
6532 if (!WriteFlags(context, result, carry))
6533 return false;
6534 }
6535 return true;
6536}
6537
6538// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6539// It updates the condition flags based on the result, and discards the result.
6540bool
6541EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6542{
6543#if 0
6544 // ARM pseudo code...
6545 if ConditionPassed() then
6546 EncodingSpecificOperations();
6547 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6548 result = R[n] AND shifted;
6549 APSR.N = result<31>;
6550 APSR.Z = IsZeroBit(result);
6551 APSR.C = carry;
6552 // APSR.V unchanged
6553#endif
6554
6555 bool success = false;
6556 const uint32_t opcode = OpcodeAsUnsigned (&success);
6557 if (!success)
6558 return false;
6559
6560 if (ConditionPassed())
6561 {
6562 uint32_t Rn, Rm;
6563 ARM_ShifterType shift_t;
6564 uint32_t shift_n; // the shift applied to the value read from Rm
6565 uint32_t carry;
6566 switch (encoding)
6567 {
6568 case eEncodingT1:
6569 Rn = Bits32(opcode, 2, 0);
6570 Rm = Bits32(opcode, 5, 3);
6571 shift_t = SRType_LSL;
6572 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006573 break;
Johnny Chende3cce32011-02-21 21:24:49 +00006574 case eEncodingT2:
6575 Rn = Bits32(opcode, 19, 16);
6576 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006577 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006578 if (BadReg(Rn) || BadReg(Rm))
6579 return false;
6580 break;
6581 case eEncodingA1:
6582 Rn = Bits32(opcode, 19, 16);
6583 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006584 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006585 break;
6586 default:
6587 return false;
6588 }
6589
6590 // Read the first operand.
6591 uint32_t val1 = ReadCoreReg(Rn, &success);
6592 if (!success)
6593 return false;
6594
6595 // Read the second operand.
6596 uint32_t val2 = ReadCoreReg(Rm, &success);
6597 if (!success)
6598 return false;
6599
6600 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6601 uint32_t result = val1 & shifted;
6602
6603 EmulateInstruction::Context context;
6604 context.type = EmulateInstruction::eContextImmediate;
6605 context.SetNoArgs ();
6606
6607 if (!WriteFlags(context, result, carry))
6608 return false;
6609 }
6610 return true;
6611}
6612
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006613EmulateInstructionARM::ARMOpcode*
6614EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006615{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006616 static ARMOpcode
6617 g_arm_opcodes[] =
6618 {
6619 //----------------------------------------------------------------------
6620 // Prologue instructions
6621 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006622
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006623 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006624 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6625 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006626
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006627 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006628 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006629 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006630 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006631 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6632 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006633 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006634
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006635 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006636 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006637
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006638 // push one register
6639 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006640 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006641
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006642 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006643 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6644 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006645
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006646 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006647 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006648 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006649
Johnny Chen9f687722011-02-18 00:02:28 +00006650 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6651 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006652 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006653 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6654
6655 //----------------------------------------------------------------------
6656 // Supervisor Call (previously Software Interrupt)
6657 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006658 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6659
6660 //----------------------------------------------------------------------
6661 // Branch instructions
6662 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006663 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006664 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6665 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6666 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6667 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006668 // for example, "bx lr"
6669 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006670
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006671 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006672 // Data-processing instructions
6673 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006674 // adc (immediate)
6675 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6676 // adc (register)
6677 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006678 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006679 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006680 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006681 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006682 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006683 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006684 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006685 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006686 // eor (immediate)
6687 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6688 // eor (register)
6689 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006690 // orr (immediate)
6691 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6692 // orr (register)
6693 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006694 // rsb (immediate)
6695 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
6696 // rsb (register)
6697 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00006698 // rsc (immediate)
6699 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
6700 // rsc (register)
6701 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00006702 // sbc (immediate)
6703 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
6704 // sbc (register)
6705 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006706 // sub (sp minus immediate)
6707 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00006708 // teq (immediate)
6709 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6710 // teq (register)
6711 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006712 // tst (immediate)
6713 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6714 // tst (register)
6715 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6716
6717
Johnny Chend642a6a2011-02-22 01:01:03 +00006718 // mvn (immediate)
6719 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6720 // mvn (register)
6721 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006722 // cmn (immediate)
6723 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6724 // cmn (register)
6725 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006726 // cmp (immediate)
6727 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6728 // cmp (register)
6729 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006730 // asr (immediate)
6731 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006732 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006733 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006734 // lsl (immediate)
6735 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6736 // lsl (register)
6737 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6738 // lsr (immediate)
6739 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6740 // lsr (register)
6741 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006742 // rrx is a special case encoding of ror (immediate)
6743 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6744 // ror (immediate)
6745 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6746 // ror (register)
6747 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006748
6749 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006750 // Load instructions
6751 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006752 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006753 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006754 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006755 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006756 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006757 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00006758 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
6759 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00006760
6761 //----------------------------------------------------------------------
6762 // Store instructions
6763 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00006764 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006765 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00006766 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00006767 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
6768 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00006769
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006770
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006771 };
6772 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
6773
6774 for (size_t i=0; i<k_num_arm_opcodes; ++i)
6775 {
6776 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
6777 return &g_arm_opcodes[i];
6778 }
6779 return NULL;
6780}
Greg Clayton64c84432011-01-21 22:02:52 +00006781
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006782
6783EmulateInstructionARM::ARMOpcode*
6784EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00006785{
Johnny Chenfdd179e2011-01-31 20:09:28 +00006786
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006787 static ARMOpcode
6788 g_thumb_opcodes[] =
6789 {
6790 //----------------------------------------------------------------------
6791 // Prologue instructions
6792 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00006793
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006794 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006795 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6796 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
6797 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00006798
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006799 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006800 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006801 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00006802 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006803 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00006804 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00006805
Johnny Chen864a8e82011-02-18 00:07:39 +00006806 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00006807 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00006808
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006809 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006810 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006811 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00006812 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
6813 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006814
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006815 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00006816 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6817 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006818
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006819 //----------------------------------------------------------------------
6820 // Epilogue instructions
6821 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00006822
Johnny Chen864a8e82011-02-18 00:07:39 +00006823 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00006824 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6825 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
6826 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00006827 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
6828 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006829
6830 //----------------------------------------------------------------------
6831 // Supervisor Call (previously Software Interrupt)
6832 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00006833 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
6834
6835 //----------------------------------------------------------------------
6836 // If Then makes up to four following instructions conditional.
6837 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006838 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
6839
6840 //----------------------------------------------------------------------
6841 // Branch instructions
6842 //----------------------------------------------------------------------
6843 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
6844 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
6845 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00006846 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006847 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00006848 // J1 == J2 == 1
6849 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6850 // J1 == J2 == 1
6851 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6852 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006853 // for example, "bx lr"
6854 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00006855 // compare and branch
6856 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00006857 // table branch byte
6858 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
6859 // table branch halfword
6860 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006861
6862 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00006863 // Data-processing instructions
6864 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006865 // adc (immediate)
6866 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
6867 // adc (register)
6868 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
6869 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
6870 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00006871 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006872 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00006873 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006874 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006875 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006876 // and (register)
6877 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
6878 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006879 // eor (immediate)
6880 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
6881 // eor (register)
6882 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
6883 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006884 // orr (immediate)
6885 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
6886 // orr (register)
6887 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
6888 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006889 // rsb (immediate)
6890 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
6891 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
6892 // rsb (register)
6893 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00006894 // sbc (immediate)
6895 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
6896 // sbc (register)
6897 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
6898 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006899 // sub (sp minus immediate)
6900 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
6901 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00006902 // teq (immediate)
6903 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
6904 // teq (register)
6905 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006906 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00006907 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00006908 // tst (register)
6909 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
6910 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
6911
Johnny Chen7c5234d2011-02-18 23:41:11 +00006912
Johnny Chen338bf542011-02-10 19:29:03 +00006913 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00006914 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00006915 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00006916 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006917 // mov{s}<c>.w <Rd>, <Rm>
6918 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00006919 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00006920 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
6921 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00006922 // mvn (immediate)
6923 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
6924 // mvn (register)
6925 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
6926 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006927 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00006928 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006929 // cmn (register)
6930 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006931 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006932 // cmp (immediate)
6933 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006934 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006935 // cmp (register) (Rn and Rm both from r0-r7)
6936 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
6937 // cmp (register) (Rn and Rm not both from r0-r7)
6938 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006939 // asr (immediate)
6940 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00006941 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00006942 // asr (register)
6943 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
6944 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006945 // lsl (immediate)
6946 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
6947 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
6948 // lsl (register)
6949 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
6950 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
6951 // lsr (immediate)
6952 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
6953 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
6954 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00006955 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006956 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006957 // rrx is a special case encoding of ror (immediate)
6958 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
6959 // ror (immediate)
6960 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
6961 // ror (register)
6962 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
6963 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006964
6965 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006966 // Load instructions
6967 //----------------------------------------------------------------------
6968 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00006969 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00006970 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00006971 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
6972 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00006973 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00006974 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
6975 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00006976 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
6977 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
6978 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00006979 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00006980 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
6981 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00006982
6983 //----------------------------------------------------------------------
6984 // Store instructions
6985 //----------------------------------------------------------------------
6986 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006987 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00006988 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00006989 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
6990 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
6991 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
6992 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
6993 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
6994 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
6995 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
6996 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
6997 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006998 };
6999
7000 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
7001 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
7002 {
7003 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
7004 return &g_thumb_opcodes[i];
7005 }
7006 return NULL;
7007}
Greg Clayton64c84432011-01-21 22:02:52 +00007008
Greg Clayton31e2a382011-01-30 20:03:56 +00007009bool
Greg Clayton395fc332011-02-15 21:59:32 +00007010EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00007011{
7012 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00007013 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00007014 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00007015 {
Greg Clayton395fc332011-02-15 21:59:32 +00007016 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
7017 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
7018 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
7019 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
7020 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
7021 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
7022 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
7023 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
7024 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
7025 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00007026 }
7027 return m_arm_isa != 0;
7028}
7029
7030
Greg Clayton64c84432011-01-21 22:02:52 +00007031bool
7032EmulateInstructionARM::ReadInstruction ()
7033{
7034 bool success = false;
7035 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
7036 if (success)
7037 {
7038 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
7039 if (success)
7040 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00007041 Context read_inst_context;
7042 read_inst_context.type = eContextReadOpcode;
7043 read_inst_context.SetNoArgs ();
7044
Greg Clayton64c84432011-01-21 22:02:52 +00007045 if (m_inst_cpsr & MASK_CPSR_T)
7046 {
7047 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007048 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007049
7050 if (success)
7051 {
7052 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
7053 {
7054 m_inst.opcode_type = eOpcode16;
7055 m_inst.opcode.inst16 = thumb_opcode;
7056 }
7057 else
7058 {
7059 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007060 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007061 }
7062 }
7063 }
7064 else
7065 {
7066 m_inst_mode = eModeARM;
7067 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007068 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007069 }
7070 }
7071 }
7072 if (!success)
7073 {
7074 m_inst_mode = eModeInvalid;
7075 m_inst_pc = LLDB_INVALID_ADDRESS;
7076 }
7077 return success;
7078}
7079
Johnny Chenee9b1f72011-02-09 01:00:31 +00007080uint32_t
7081EmulateInstructionARM::ArchVersion ()
7082{
7083 return m_arm_isa;
7084}
7085
Greg Clayton64c84432011-01-21 22:02:52 +00007086bool
7087EmulateInstructionARM::ConditionPassed ()
7088{
7089 if (m_inst_cpsr == 0)
7090 return false;
7091
7092 const uint32_t cond = CurrentCond ();
7093
7094 if (cond == UINT32_MAX)
7095 return false;
7096
7097 bool result = false;
7098 switch (UnsignedBits(cond, 3, 1))
7099 {
7100 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
7101 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
7102 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
7103 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
7104 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
7105 case 5:
7106 {
7107 bool n = (m_inst_cpsr & MASK_CPSR_N);
7108 bool v = (m_inst_cpsr & MASK_CPSR_V);
7109 result = n == v;
7110 }
7111 break;
7112 case 6:
7113 {
7114 bool n = (m_inst_cpsr & MASK_CPSR_N);
7115 bool v = (m_inst_cpsr & MASK_CPSR_V);
7116 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
7117 }
7118 break;
7119 case 7:
7120 result = true;
7121 break;
7122 }
7123
7124 if (cond & 1)
7125 result = !result;
7126 return result;
7127}
7128
Johnny Chen9ee056b2011-02-08 00:06:35 +00007129uint32_t
7130EmulateInstructionARM::CurrentCond ()
7131{
7132 switch (m_inst_mode)
7133 {
7134 default:
7135 case eModeInvalid:
7136 break;
7137
7138 case eModeARM:
7139 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
7140
7141 case eModeThumb:
7142 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
7143 // 'cond' field of the encoding.
7144 if (m_inst.opcode_type == eOpcode16 &&
7145 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
7146 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
7147 {
7148 return Bits32(m_inst.opcode.inst16, 11, 7);
7149 }
7150 else if (m_inst.opcode_type == eOpcode32 &&
7151 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
7152 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
7153 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
7154 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
7155 {
7156 return Bits32(m_inst.opcode.inst32, 25, 22);
7157 }
7158
7159 return m_it_session.GetCond();
7160 }
7161 return UINT32_MAX; // Return invalid value
7162}
7163
Johnny Chen9ee056b2011-02-08 00:06:35 +00007164bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00007165EmulateInstructionARM::InITBlock()
7166{
7167 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
7168}
7169
7170bool
7171EmulateInstructionARM::LastInITBlock()
7172{
7173 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
7174}
7175
7176bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00007177EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
7178{
7179 addr_t target;
7180
Johnny Chenee9b1f72011-02-09 01:00:31 +00007181 // Check the current instruction set.
7182 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007183 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007184 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00007185 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007186
Johnny Chen9ee056b2011-02-08 00:06:35 +00007187 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007188 return false;
7189
7190 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007191}
7192
7193// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
7194bool
Johnny Chen668b4512011-02-15 21:08:58 +00007195EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007196{
7197 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00007198 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
7199 // we want to record it and issue a WriteRegister callback so the clients
7200 // can track the mode changes accordingly.
7201 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007202
7203 if (BitIsSet(addr, 0))
7204 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007205 if (CurrentInstrSet() != eModeThumb)
7206 {
7207 SelectInstrSet(eModeThumb);
7208 cpsr_changed = true;
7209 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007210 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00007211 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007212 }
7213 else if (BitIsClear(addr, 1))
7214 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007215 if (CurrentInstrSet() != eModeARM)
7216 {
7217 SelectInstrSet(eModeARM);
7218 cpsr_changed = true;
7219 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007220 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00007221 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007222 }
7223 else
7224 return false; // address<1:0> == '10' => UNPREDICTABLE
7225
Johnny Chen0f309db2011-02-09 19:11:32 +00007226 if (cpsr_changed)
7227 {
Johnny Chen558133b2011-02-09 23:59:17 +00007228 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00007229 return false;
7230 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007231 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007232 return false;
7233
7234 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007235}
Greg Clayton64c84432011-01-21 22:02:52 +00007236
Johnny Chenee9b1f72011-02-09 01:00:31 +00007237// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
7238bool
Johnny Chen668b4512011-02-15 21:08:58 +00007239EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00007240{
7241 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00007242 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00007243 else
7244 return BranchWritePC((const Context)context, addr);
7245}
7246
Johnny Chen26863dc2011-02-09 23:43:29 +00007247// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
7248bool
Johnny Chen668b4512011-02-15 21:08:58 +00007249EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00007250{
7251 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00007252 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00007253 else
7254 return BranchWritePC((const Context)context, addr);
7255}
7256
Johnny Chenee9b1f72011-02-09 01:00:31 +00007257EmulateInstructionARM::Mode
7258EmulateInstructionARM::CurrentInstrSet ()
7259{
7260 return m_inst_mode;
7261}
7262
7263// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00007264// ReadInstruction() is performed. This function has a side effect of updating
7265// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00007266bool
7267EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
7268{
Johnny Chen558133b2011-02-09 23:59:17 +00007269 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007270 switch (arm_or_thumb)
7271 {
7272 default:
7273 return false;
7274 eModeARM:
7275 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007276 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007277 break;
7278 eModeThumb:
7279 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007280 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007281 break;
7282 }
7283 return true;
7284}
7285
Johnny Chenef21b592011-02-10 01:52:38 +00007286// This function returns TRUE if the processor currently provides support for
7287// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
7288// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
7289bool
7290EmulateInstructionARM::UnalignedSupport()
7291{
7292 return (ArchVersion() >= ARMv7);
7293}
7294
Johnny Chenbf6ad172011-02-11 01:29:53 +00007295// The main addition and subtraction instructions can produce status information
7296// about both unsigned carry and signed overflow conditions. This status
7297// information can be used to synthesize multi-word additions and subtractions.
7298EmulateInstructionARM::AddWithCarryResult
7299EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
7300{
7301 uint32_t result;
7302 uint8_t carry_out;
7303 uint8_t overflow;
7304
7305 uint64_t unsigned_sum = x + y + carry_in;
7306 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
7307
7308 result = UnsignedBits(unsigned_sum, 31, 0);
7309 carry_out = (result == unsigned_sum ? 0 : 1);
7310 overflow = ((int32_t)result == signed_sum ? 0 : 1);
7311
7312 AddWithCarryResult res = { result, carry_out, overflow };
7313 return res;
7314}
7315
Johnny Chen157b9592011-02-18 21:13:05 +00007316uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00007317EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00007318{
Johnny Chene39f22d2011-02-19 01:36:13 +00007319 uint32_t reg_kind, reg_num;
7320 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00007321 {
Johnny Chene39f22d2011-02-19 01:36:13 +00007322 case SP_REG:
7323 reg_kind = eRegisterKindGeneric;
7324 reg_num = LLDB_REGNUM_GENERIC_SP;
7325 break;
7326 case LR_REG:
7327 reg_kind = eRegisterKindGeneric;
7328 reg_num = LLDB_REGNUM_GENERIC_RA;
7329 break;
7330 case PC_REG:
7331 reg_kind = eRegisterKindGeneric;
7332 reg_num = LLDB_REGNUM_GENERIC_PC;
7333 break;
7334 default:
7335 if (0 <= num && num < SP_REG)
7336 {
7337 reg_kind = eRegisterKindDWARF;
7338 reg_num = dwarf_r0 + num;
7339 }
Johnny Chen157b9592011-02-18 21:13:05 +00007340 else
Johnny Chene39f22d2011-02-19 01:36:13 +00007341 {
7342 assert(0 && "Invalid register number");
7343 *success = false;
7344 return ~0u;
7345 }
7346 break;
Johnny Chen157b9592011-02-18 21:13:05 +00007347 }
Johnny Chene39f22d2011-02-19 01:36:13 +00007348
7349 // Read our register.
7350 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
7351
7352 // When executing an ARM instruction , PC reads as the address of the current
7353 // instruction plus 8.
7354 // When executing a Thumb instruction , PC reads as the address of the current
7355 // instruction plus 4.
7356 if (num == 15)
7357 {
7358 if (CurrentInstrSet() == eModeARM)
7359 val += 8;
7360 else
7361 val += 4;
7362 }
Johnny Chen157b9592011-02-18 21:13:05 +00007363
7364 return val;
7365}
7366
Johnny Chenca67d1c2011-02-17 01:35:27 +00007367// Write the result to the ARM core register Rd, and optionally update the
7368// condition flags based on the result.
7369//
7370// This helper method tries to encapsulate the following pseudocode from the
7371// ARM Architecture Reference Manual:
7372//
7373// if d == 15 then // Can only occur for encoding A1
7374// ALUWritePC(result); // setflags is always FALSE here
7375// else
7376// R[d] = result;
7377// if setflags then
7378// APSR.N = result<31>;
7379// APSR.Z = IsZeroBit(result);
7380// APSR.C = carry;
7381// // APSR.V unchanged
7382//
7383// In the above case, the API client does not pass in the overflow arg, which
7384// defaults to ~0u.
7385bool
Johnny Chen10530c22011-02-17 22:37:12 +00007386EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
7387 const uint32_t result,
7388 const uint32_t Rd,
7389 bool setflags,
7390 const uint32_t carry,
7391 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00007392{
7393 if (Rd == 15)
7394 {
7395 if (!ALUWritePC (context, result))
7396 return false;
7397 }
7398 else
7399 {
7400 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
7401 return false;
7402 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00007403 return WriteFlags (context, result, carry, overflow);
7404 }
7405 return true;
7406}
7407
7408// This helper method tries to encapsulate the following pseudocode from the
7409// ARM Architecture Reference Manual:
7410//
7411// APSR.N = result<31>;
7412// APSR.Z = IsZeroBit(result);
7413// APSR.C = carry;
7414// APSR.V = overflow
7415//
7416// Default arguments can be specified for carry and overflow parameters, which means
7417// not to update the respective flags.
7418bool
7419EmulateInstructionARM::WriteFlags (Context &context,
7420 const uint32_t result,
7421 const uint32_t carry,
7422 const uint32_t overflow)
7423{
7424 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00007425 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
7426 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00007427 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007428 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00007429 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007430 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00007431 if (m_new_inst_cpsr != m_inst_cpsr)
7432 {
7433 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
7434 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00007435 }
7436 return true;
7437}
7438
Greg Clayton64c84432011-01-21 22:02:52 +00007439bool
7440EmulateInstructionARM::EvaluateInstruction ()
7441{
Johnny Chenc315f862011-02-05 00:46:10 +00007442 // Advance the ITSTATE bits to their values for the next instruction.
7443 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
7444 m_it_session.ITAdvance();
7445
Greg Clayton64c84432011-01-21 22:02:52 +00007446 return false;
7447}