blob: 9dcd4e5d65387704a2d38b8a4c9669e89af48c88 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
132#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000133
Johnny Chen0e00af22011-02-10 19:40:42 +0000134//----------------------------------------------------------------------
135//
136// EmulateInstructionARM implementation
137//
138//----------------------------------------------------------------------
139
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140void
141EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145void
146EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000147{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000148}
149
Caroline Ticefa172202011-02-11 22:49:54 +0000150// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
151bool
152EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
153{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000154 EmulateInstruction::Context context;
155 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
156 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000157
158 uint32_t random_data = rand ();
159 const uint32_t addr_byte_size = GetAddressByteSize();
160
Caroline Ticecc96eb52011-02-17 19:20:40 +0000161 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000162 return false;
163
164 return true;
165}
166
Caroline Tice713c2662011-02-11 17:59:55 +0000167// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
168bool
169EmulateInstructionARM::WriteBits32Unknown (int n)
170{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000171 EmulateInstruction::Context context;
172 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
173 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000174
Johnny Chen62ff6f52011-02-11 18:11:22 +0000175 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
177
178 if (!success)
179 return false;
180
181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
182 return false;
183
184 return true;
185}
186
Johnny Chen08c25e82011-01-31 18:02:28 +0000187// Push Multiple Registers stores multiple registers to the stack, storing to
188// consecutive memory locations ending just below the address in SP, and updates
189// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000190bool
Johnny Chen9f687722011-02-18 00:02:28 +0000191EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000192{
193#if 0
194 // ARM pseudo code...
195 if (ConditionPassed())
196 {
197 EncodingSpecificOperations();
198 NullCheckIfThumbEE(13);
199 address = SP - 4*BitCount(registers);
200
201 for (i = 0 to 14)
202 {
203 if (registers<i> == ’1’)
204 {
205 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
206 MemA[address,4] = bits(32) UNKNOWN;
207 else
208 MemA[address,4] = R[i];
209 address = address + 4;
210 }
211 }
212
213 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
214 MemA[address,4] = PCStoreValue();
215
216 SP = SP - 4*BitCount(registers);
217 }
218#endif
219
220 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000222 if (!success)
223 return false;
224
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000228 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000232 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000235 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000237 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000238 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000239 // if BitCount(registers) < 1 then UNPREDICTABLE;
240 if (BitCount(registers) < 1)
241 return false;
242 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 case eEncodingT2:
244 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000245 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000246 // if BitCount(registers) < 2 then UNPREDICTABLE;
247 if (BitCount(registers) < 2)
248 return false;
249 break;
250 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000251 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000257 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000258 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000259 // Instead of return false, let's handle the following case as well,
260 // which amounts to pushing one reg onto the full descending stacks.
261 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000262 break;
263 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000264 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000265 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000270 default:
271 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000272 }
Johnny Chence1ca772011-01-25 01:13:00 +0000273 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000274 addr_t addr = sp - sp_offset;
275 uint32_t i;
276
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000277 EmulateInstruction::Context context;
278 context.type = EmulateInstruction::eContextPushRegisterOnStack;
279 Register dwarf_reg;
280 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000281 for (i=0; i<15; ++i)
282 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000283 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000285 dwarf_reg.num = dwarf_r0 + i;
286 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000290 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000291 return false;
292 addr += addr_byte_size;
293 }
294 }
295
Johnny Chen7c1bf922011-02-08 23:49:37 +0000296 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000297 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000298 dwarf_reg.num = dwarf_pc;
299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000300 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000301 if (!success)
302 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000303 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000304 return false;
305 }
306
307 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000308 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000309
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000311 return false;
312 }
313 return true;
314}
315
Johnny Chenef85e912011-01-31 23:07:40 +0000316// Pop Multiple Registers loads multiple registers from the stack, loading from
317// consecutive memory locations staring at the address in SP, and updates
318// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319bool
Johnny Chen9f687722011-02-18 00:02:28 +0000320EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000321{
322#if 0
323 // ARM pseudo code...
324 if (ConditionPassed())
325 {
326 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
327 address = SP;
328 for i = 0 to 14
329 if registers<i> == ‘1’ then
330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
331 if registers<15> == ‘1’ then
332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
336 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
337 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
338 }
339#endif
340
341 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000343 if (!success)
344 return false;
345
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000347 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000349 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000350 if (!success)
351 return false;
352 uint32_t registers = 0;
353 uint32_t Rt; // the destination register
354 switch (encoding) {
355 case eEncodingT1:
356 registers = Bits32(opcode, 7, 0);
357 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000358 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000359 registers |= (1u << 15);
360 // if BitCount(registers) < 1 then UNPREDICTABLE;
361 if (BitCount(registers) < 1)
362 return false;
363 break;
364 case eEncodingT2:
365 // Ignore bit 13.
366 registers = Bits32(opcode, 15, 0) & ~0x2000;
367 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000368 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000370 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
371 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
372 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000373 break;
374 case eEncodingT3:
375 Rt = Bits32(opcode, 15, 12);
376 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000377 if (Rt == 13)
378 return false;
379 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000380 return false;
381 registers = (1u << Rt);
382 break;
383 case eEncodingA1:
384 registers = Bits32(opcode, 15, 0);
385 // Instead of return false, let's handle the following case as well,
386 // which amounts to popping one reg from the full descending stacks.
387 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
388
389 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000390 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000391 return false;
392 break;
393 case eEncodingA2:
394 Rt = Bits32(opcode, 15, 12);
395 // if t == 13 then UNPREDICTABLE;
396 if (Rt == dwarf_sp)
397 return false;
398 registers = (1u << Rt);
399 break;
400 default:
401 return false;
402 }
403 addr_t sp_offset = addr_byte_size * BitCount (registers);
404 addr_t addr = sp;
405 uint32_t i, data;
406
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000407 EmulateInstruction::Context context;
408 context.type = EmulateInstruction::eContextPopRegisterOffStack;
409 Register dwarf_reg;
410 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000411 for (i=0; i<15; ++i)
412 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000413 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 dwarf_reg.num = dwarf_r0 + i;
416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000417 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000418 if (!success)
419 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 return false;
422 addr += addr_byte_size;
423 }
424 }
425
Johnny Chen7c1bf922011-02-08 23:49:37 +0000426 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000428 dwarf_reg.num = dwarf_pc;
429 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000430 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000431 if (!success)
432 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000433 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000434 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 addr += addr_byte_size;
437 }
438
439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000440 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000441
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 }
445 return true;
446}
447
Johnny Chen5b442b72011-01-27 19:34:30 +0000448// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000450bool
Johnny Chen9f687722011-02-18 00:02:28 +0000451EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000452{
453#if 0
454 // ARM pseudo code...
455 if (ConditionPassed())
456 {
457 EncodingSpecificOperations();
458 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
459 if d == 15 then
460 ALUWritePC(result); // setflags is always FALSE here
461 else
462 R[d] = result;
463 if setflags then
464 APSR.N = result<31>;
465 APSR.Z = IsZeroBit(result);
466 APSR.C = carry;
467 APSR.V = overflow;
468 }
469#endif
470
471 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 if (!success)
474 return false;
475
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000478 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481 uint32_t Rd; // the destination register
482 uint32_t imm32;
483 switch (encoding) {
484 case eEncodingT1:
485 Rd = 7;
486 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
487 break;
488 case eEncodingA1:
489 Rd = Bits32(opcode, 15, 12);
490 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
491 break;
492 default:
493 return false;
494 }
495 addr_t sp_offset = imm32;
496 addr_t addr = sp + sp_offset; // a pointer to the stack area
497
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000498 EmulateInstruction::Context context;
499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
500 Register sp_reg;
501 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
502 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000505 return false;
506 }
507 return true;
508}
509
Johnny Chen2ccad832011-01-28 19:57:25 +0000510// Set r7 or ip to the current stack pointer.
511// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000512bool
Johnny Chen9f687722011-02-18 00:02:28 +0000513EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000514{
515#if 0
516 // ARM pseudo code...
517 if (ConditionPassed())
518 {
519 EncodingSpecificOperations();
520 result = R[m];
521 if d == 15 then
522 ALUWritePC(result); // setflags is always FALSE here
523 else
524 R[d] = result;
525 if setflags then
526 APSR.N = result<31>;
527 APSR.Z = IsZeroBit(result);
528 // APSR.C unchanged
529 // APSR.V unchanged
530 }
531#endif
532
533 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000535 //if (!success)
536 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000537
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000540 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000541 if (!success)
542 return false;
543 uint32_t Rd; // the destination register
544 switch (encoding) {
545 case eEncodingT1:
546 Rd = 7;
547 break;
548 case eEncodingA1:
549 Rd = 12;
550 break;
551 default:
552 return false;
553 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000554
555 EmulateInstruction::Context context;
556 context.type = EmulateInstruction::eContextRegisterPlusOffset;
557 Register sp_reg;
558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
559 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000560
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000562 return false;
563 }
564 return true;
565}
566
Johnny Chen1c13b622011-01-29 00:11:15 +0000567// Move from high register (r8-r15) to low register (r0-r7).
568// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569bool
Johnny Chen9f687722011-02-18 00:02:28 +0000570EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000571{
Johnny Chen9f687722011-02-18 00:02:28 +0000572 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000573}
574
575// Move from register to register.
576// MOV (register)
577bool
Johnny Chen9f687722011-02-18 00:02:28 +0000578EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000579{
Johnny Chen1c13b622011-01-29 00:11:15 +0000580#if 0
581 // ARM pseudo code...
582 if (ConditionPassed())
583 {
584 EncodingSpecificOperations();
585 result = R[m];
586 if d == 15 then
587 ALUWritePC(result); // setflags is always FALSE here
588 else
589 R[d] = result;
590 if setflags then
591 APSR.N = result<31>;
592 APSR.Z = IsZeroBit(result);
593 // APSR.C unchanged
594 // APSR.V unchanged
595 }
596#endif
597
598 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 if (!success)
601 return false;
602
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000603 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 {
605 uint32_t Rm; // the source register
606 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000607 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000608 switch (encoding) {
609 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000610 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000612 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000613 if (Rd == 15 && InITBlock() && !LastInITBlock())
614 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000615 break;
616 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000617 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000620 if (InITBlock())
621 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000622 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 case eEncodingT3:
624 Rd = Bits32(opcode, 11, 8);
625 Rm = Bits32(opcode, 3, 0);
626 setflags = BitIsSet(opcode, 20);
627 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
628 if (setflags && (BadReg(Rd) || BadReg(Rm)))
629 return false;
630 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
631 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
632 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000633 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000634 default:
635 return false;
636 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000637 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000638 if (!success)
639 return false;
640
641 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000642 EmulateInstruction::Context context;
643 context.type = EmulateInstruction::eContextRegisterPlusOffset;
644 Register dwarf_reg;
645 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
646 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000647
Johnny Chen10530c22011-02-17 22:37:12 +0000648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000649 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
Johnny Chen9f687722011-02-18 00:02:28 +0000658EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
677 bool success = false;
678 const uint32_t opcode = OpcodeAsUnsigned (&success);
679 if (!success)
680 return false;
681
682 if (ConditionPassed())
683 {
684 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000685 uint32_t imm32; // the immediate value to be written to Rd
686 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
687 bool setflags;
688 switch (encoding) {
689 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000690 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000691 setflags = !InITBlock();
692 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000693 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000694 break;
695 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000696 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000697 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000698 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000699 if (BadReg(Rd))
700 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000701 break;
702 default:
703 return false;
704 }
705 uint32_t result = imm32;
706
707 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000708 EmulateInstruction::Context context;
709 context.type = EmulateInstruction::eContextImmediate;
710 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000711
Johnny Chen10530c22011-02-17 22:37:12 +0000712 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000713 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000714 }
715 return true;
716}
717
Johnny Chend642a6a2011-02-22 01:01:03 +0000718// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
719// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000720bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000721EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000722{
723#if 0
724 // ARM pseudo code...
725 if (ConditionPassed())
726 {
727 EncodingSpecificOperations();
728 result = NOT(imm32);
729 if d == 15 then // Can only occur for ARM encoding
730 ALUWritePC(result); // setflags is always FALSE here
731 else
732 R[d] = result;
733 if setflags then
734 APSR.N = result<31>;
735 APSR.Z = IsZeroBit(result);
736 APSR.C = carry;
737 // APSR.V unchanged
738 }
739#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000740 bool success = false;
741 const uint32_t opcode = OpcodeAsUnsigned (&success);
742 if (!success)
743 return false;
744
745 if (ConditionPassed())
746 {
747 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000748 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
749 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000750 bool setflags;
751 switch (encoding) {
752 case eEncodingT1:
753 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000754 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000755 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000756 break;
757 case eEncodingA1:
758 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000759 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000760 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
761 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
762 // TODO: Emulate SUBS PC, LR and related instructions.
763 if (Rd == 15 && setflags)
764 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 break;
766 default:
767 return false;
768 }
769 uint32_t result = ~imm32;
770
771 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000772 EmulateInstruction::Context context;
773 context.type = EmulateInstruction::eContextImmediate;
774 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000775
Johnny Chen10530c22011-02-17 22:37:12 +0000776 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000777 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000778 }
779 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000780}
781
Johnny Chend642a6a2011-02-22 01:01:03 +0000782// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
783// It can optionally update the condition flags based on the result.
784bool
785EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
786{
787#if 0
788 // ARM pseudo code...
789 if (ConditionPassed())
790 {
791 EncodingSpecificOperations();
792 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
793 result = NOT(shifted);
794 if d == 15 then // Can only occur for ARM encoding
795 ALUWritePC(result); // setflags is always FALSE here
796 else
797 R[d] = result;
798 if setflags then
799 APSR.N = result<31>;
800 APSR.Z = IsZeroBit(result);
801 APSR.C = carry;
802 // APSR.V unchanged
803 }
804#endif
805
806 bool success = false;
807 const uint32_t opcode = OpcodeAsUnsigned (&success);
808 if (!success)
809 return false;
810
811 if (ConditionPassed())
812 {
813 uint32_t Rm; // the source register
814 uint32_t Rd; // the destination register
815 ARM_ShifterType shift_t;
816 uint32_t shift_n; // the shift applied to the value read from Rm
817 bool setflags;
818 uint32_t carry; // the carry bit after the shift operation
819 switch (encoding) {
820 case eEncodingT1:
821 Rd = Bits32(opcode, 2, 0);
822 Rm = Bits32(opcode, 5, 3);
823 setflags = !InITBlock();
824 shift_t = SRType_LSL;
825 shift_n = 0;
826 if (InITBlock())
827 return false;
828 break;
829 case eEncodingT2:
830 Rd = Bits32(opcode, 11, 8);
831 Rm = Bits32(opcode, 3, 0);
832 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000833 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000834 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000835 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000836 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000837 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000838 case eEncodingA1:
839 Rd = Bits32(opcode, 15, 12);
840 Rm = Bits32(opcode, 3, 0);
841 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000842 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000843 break;
844 default:
845 return false;
846 }
847 uint32_t value = ReadCoreReg(Rm, &success);
848 if (!success)
849 return false;
850
851 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
852 uint32_t result = ~shifted;
853
854 // The context specifies that an immediate is to be moved into Rd.
855 EmulateInstruction::Context context;
856 context.type = EmulateInstruction::eContextImmediate;
857 context.SetNoArgs ();
858
859 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
860 return false;
861 }
862 return true;
863}
864
Johnny Chen788e0552011-01-27 22:52:23 +0000865// PC relative immediate load into register, possibly followed by ADD (SP plus register).
866// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000867bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000868EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000869{
870#if 0
871 // ARM pseudo code...
872 if (ConditionPassed())
873 {
874 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
875 base = Align(PC,4);
876 address = if add then (base + imm32) else (base - imm32);
877 data = MemU[address,4];
878 if t == 15 then
879 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
880 elsif UnalignedSupport() || address<1:0> = ‘00’ then
881 R[t] = data;
882 else // Can only apply before ARMv7
883 if CurrentInstrSet() == InstrSet_ARM then
884 R[t] = ROR(data, 8*UInt(address<1:0>));
885 else
886 R[t] = bits(32) UNKNOWN;
887 }
888#endif
889
890 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000891 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000892 if (!success)
893 return false;
894
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000895 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000896 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000897 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000898 if (!success)
899 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000900
901 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000902 EmulateInstruction::Context context;
903 context.type = EmulateInstruction::eContextRegisterPlusOffset;
904 Register pc_reg;
905 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
906 context.SetRegisterPlusOffset (pc_reg, 0);
907
Johnny Chenc9de9102011-02-11 19:12:30 +0000908 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000909 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000910 bool add; // +imm32 or -imm32?
911 addr_t base; // the base address
912 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000913 uint32_t data; // the literal data value from the PC relative load
914 switch (encoding) {
915 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000916 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000917 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000918 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000919 break;
920 case eEncodingT2:
921 Rt = Bits32(opcode, 15, 12);
922 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
923 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000924 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000925 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000926 break;
927 default:
928 return false;
929 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000930
Johnny Chene39f22d2011-02-19 01:36:13 +0000931 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000932 if (add)
933 address = base + imm32;
934 else
935 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000936
937 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000938 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000939 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000940 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000941
942 if (Rt == 15)
943 {
944 if (Bits32(address, 1, 0) == 0)
945 {
946 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000947 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000948 return false;
949 }
950 else
951 return false;
952 }
953 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
954 {
955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
956 return false;
957 }
958 else // We don't handle ARM for now.
959 return false;
960
961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000962 return false;
963 }
964 return true;
965}
966
Johnny Chen5b442b72011-01-27 19:34:30 +0000967// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000968// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000969bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000970EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000971{
972#if 0
973 // ARM pseudo code...
974 if (ConditionPassed())
975 {
976 EncodingSpecificOperations();
977 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
978 if d == 15 then // Can only occur for ARM encoding
979 ALUWritePC(result); // setflags is always FALSE here
980 else
981 R[d] = result;
982 if setflags then
983 APSR.N = result<31>;
984 APSR.Z = IsZeroBit(result);
985 APSR.C = carry;
986 APSR.V = overflow;
987 }
988#endif
989
990 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000991 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000992 if (!success)
993 return false;
994
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000995 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000996 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000997 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000998 if (!success)
999 return false;
1000 uint32_t imm32; // the immediate operand
1001 switch (encoding) {
1002 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001003 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001004 break;
1005 default:
1006 return false;
1007 }
1008 addr_t sp_offset = imm32;
1009 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1010
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001011 EmulateInstruction::Context context;
1012 context.type = EmulateInstruction::eContextAdjustStackPointer;
1013 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001014
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001015 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001016 return false;
1017 }
1018 return true;
1019}
1020
1021// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001022// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001023bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001024EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001025{
1026#if 0
1027 // ARM pseudo code...
1028 if (ConditionPassed())
1029 {
1030 EncodingSpecificOperations();
1031 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1032 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1033 if d == 15 then
1034 ALUWritePC(result); // setflags is always FALSE here
1035 else
1036 R[d] = result;
1037 if setflags then
1038 APSR.N = result<31>;
1039 APSR.Z = IsZeroBit(result);
1040 APSR.C = carry;
1041 APSR.V = overflow;
1042 }
1043#endif
1044
1045 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001046 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001047 if (!success)
1048 return false;
1049
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001050 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001051 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001052 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001053 if (!success)
1054 return false;
1055 uint32_t Rm; // the second operand
1056 switch (encoding) {
1057 case eEncodingT2:
1058 Rm = Bits32(opcode, 6, 3);
1059 break;
1060 default:
1061 return false;
1062 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001063 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001064 if (!success)
1065 return false;
1066
1067 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1068
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001069 EmulateInstruction::Context context;
1070 context.type = EmulateInstruction::eContextAdjustStackPointer;
1071 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001072
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001073 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001074 return false;
1075 }
1076 return true;
1077}
1078
Johnny Chen9b8d7832011-02-02 01:13:56 +00001079// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1080// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1081// from Thumb to ARM.
1082// BLX (immediate)
1083bool
1084EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1085{
1086#if 0
1087 // ARM pseudo code...
1088 if (ConditionPassed())
1089 {
1090 EncodingSpecificOperations();
1091 if CurrentInstrSet() == InstrSet_ARM then
1092 LR = PC - 4;
1093 else
1094 LR = PC<31:1> : '1';
1095 if targetInstrSet == InstrSet_ARM then
1096 targetAddress = Align(PC,4) + imm32;
1097 else
1098 targetAddress = PC + imm32;
1099 SelectInstrSet(targetInstrSet);
1100 BranchWritePC(targetAddress);
1101 }
1102#endif
1103
1104 bool success = false;
1105 const uint32_t opcode = OpcodeAsUnsigned (&success);
1106 if (!success)
1107 return false;
1108
1109 if (ConditionPassed())
1110 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001111 EmulateInstruction::Context context;
1112 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001113 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001114 if (!success)
1115 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001116 addr_t lr; // next instruction address
1117 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001118 int32_t imm32; // PC-relative offset
1119 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001120 case eEncodingT1:
1121 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001122 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001123 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001124 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001125 uint32_t J1 = Bit32(opcode, 13);
1126 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001127 uint32_t imm11 = Bits32(opcode, 10, 0);
1128 uint32_t I1 = !(J1 ^ S);
1129 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001130 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001131 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001132 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001133 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001134 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001135 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001136 break;
1137 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001138 case eEncodingT2:
1139 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001140 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001141 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001142 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001143 uint32_t J1 = Bit32(opcode, 13);
1144 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001145 uint32_t imm10L = Bits32(opcode, 10, 1);
1146 uint32_t I1 = !(J1 ^ S);
1147 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001148 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001149 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001150 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001151 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001152 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001153 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001154 break;
1155 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001156 case eEncodingA1:
1157 lr = pc + 4; // return address
1158 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001159 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001160 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001161 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001162 case eEncodingA2:
1163 lr = pc + 4; // return address
1164 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001165 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001166 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001167 break;
1168 default:
1169 return false;
1170 }
1171 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1172 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001173 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001174 return false;
1175 }
1176 return true;
1177}
1178
1179// Branch with Link and Exchange (register) calls a subroutine at an address and
1180// instruction set specified by a register.
1181// BLX (register)
1182bool
1183EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1184{
1185#if 0
1186 // ARM pseudo code...
1187 if (ConditionPassed())
1188 {
1189 EncodingSpecificOperations();
1190 target = R[m];
1191 if CurrentInstrSet() == InstrSet_ARM then
1192 next_instr_addr = PC - 4;
1193 LR = next_instr_addr;
1194 else
1195 next_instr_addr = PC - 2;
1196 LR = next_instr_addr<31:1> : ‘1’;
1197 BXWritePC(target);
1198 }
1199#endif
1200
1201 bool success = false;
1202 const uint32_t opcode = OpcodeAsUnsigned (&success);
1203 if (!success)
1204 return false;
1205
1206 if (ConditionPassed())
1207 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001208 EmulateInstruction::Context context;
1209 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001210 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001211 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001212 if (!success)
1213 return false;
1214 uint32_t Rm; // the register with the target address
1215 switch (encoding) {
1216 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001217 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001218 Rm = Bits32(opcode, 6, 3);
1219 // if m == 15 then UNPREDICTABLE;
1220 if (Rm == 15)
1221 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001222 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001223 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001224 break;
1225 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001226 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001227 Rm = Bits32(opcode, 3, 0);
1228 // if m == 15 then UNPREDICTABLE;
1229 if (Rm == 15)
1230 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001231 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001232 default:
1233 return false;
1234 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001235 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001236 if (!success)
1237 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001238 Register dwarf_reg;
1239 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1240 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001241 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1242 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001243 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001244 return false;
1245 }
1246 return true;
1247}
1248
Johnny Chenab3b3512011-02-12 00:10:51 +00001249// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1250// BX
1251bool
1252EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1253{
1254#if 0
1255 // ARM pseudo code...
1256 if (ConditionPassed())
1257 {
1258 EncodingSpecificOperations();
1259 BXWritePC(R[m]);
1260 }
1261#endif
1262
1263 bool success = false;
1264 const uint32_t opcode = OpcodeAsUnsigned (&success);
1265 if (!success)
1266 return false;
1267
1268 if (ConditionPassed())
1269 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001270 EmulateInstruction::Context context;
1271 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001272 uint32_t Rm; // the register with the target address
1273 switch (encoding) {
1274 case eEncodingT1:
1275 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001276 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001277 return false;
1278 break;
1279 case eEncodingA1:
1280 Rm = Bits32(opcode, 3, 0);
1281 break;
1282 default:
1283 return false;
1284 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001285 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001286 if (!success)
1287 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001288
1289 Register dwarf_reg;
1290 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001291 context.SetRegister (dwarf_reg);
1292 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001293 return false;
1294 }
1295 return true;
1296}
1297
Johnny Chen0d0148e2011-01-28 02:26:08 +00001298// Set r7 to point to some ip offset.
1299// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001300bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001301EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001302{
1303#if 0
1304 // ARM pseudo code...
1305 if (ConditionPassed())
1306 {
1307 EncodingSpecificOperations();
1308 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1309 if d == 15 then // Can only occur for ARM encoding
1310 ALUWritePC(result); // setflags is always FALSE here
1311 else
1312 R[d] = result;
1313 if setflags then
1314 APSR.N = result<31>;
1315 APSR.Z = IsZeroBit(result);
1316 APSR.C = carry;
1317 APSR.V = overflow;
1318 }
1319#endif
1320
1321 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001322 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001323 if (!success)
1324 return false;
1325
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001326 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001327 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001328 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001329 if (!success)
1330 return false;
1331 uint32_t imm32;
1332 switch (encoding) {
1333 case eEncodingA1:
1334 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1335 break;
1336 default:
1337 return false;
1338 }
1339 addr_t ip_offset = imm32;
1340 addr_t addr = ip - ip_offset; // the adjusted ip value
1341
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001342 EmulateInstruction::Context context;
1343 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1344 Register dwarf_reg;
1345 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1346 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001348 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001349 return false;
1350 }
1351 return true;
1352}
1353
1354// Set ip to point to some stack offset.
1355// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001356bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001357EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001358{
1359#if 0
1360 // ARM pseudo code...
1361 if (ConditionPassed())
1362 {
1363 EncodingSpecificOperations();
1364 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1365 if d == 15 then // Can only occur for ARM encoding
1366 ALUWritePC(result); // setflags is always FALSE here
1367 else
1368 R[d] = result;
1369 if setflags then
1370 APSR.N = result<31>;
1371 APSR.Z = IsZeroBit(result);
1372 APSR.C = carry;
1373 APSR.V = overflow;
1374 }
1375#endif
1376
1377 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001378 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001379 if (!success)
1380 return false;
1381
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001382 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001383 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001384 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001385 if (!success)
1386 return false;
1387 uint32_t imm32;
1388 switch (encoding) {
1389 case eEncodingA1:
1390 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1391 break;
1392 default:
1393 return false;
1394 }
1395 addr_t sp_offset = imm32;
1396 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1397
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001398 EmulateInstruction::Context context;
1399 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1400 Register dwarf_reg;
1401 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1402 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001403
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001405 return false;
1406 }
1407 return true;
1408}
1409
Johnny Chenc9e747f2011-02-23 01:55:07 +00001410// This instruction subtracts an immediate value from the SP value, and writes
1411// the result to the destination register.
1412//
1413// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001414bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001415EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001416{
1417#if 0
1418 // ARM pseudo code...
1419 if (ConditionPassed())
1420 {
1421 EncodingSpecificOperations();
1422 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
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 Chena695f952011-02-23 21:24:25 +00001453 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001454 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001455 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001456 Rd = Bits32(opcode, 11, 8);
1457 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001458 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001459 if (Rd == 15 && setflags)
1460 return EmulateCMPImm(eEncodingT2);
1461 if (Rd == 15 && !setflags)
1462 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001463 break;
1464 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001465 Rd = Bits32(opcode, 11, 8);
1466 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001467 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
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 Chena695f952011-02-23 21:24:25 +00004667// This instruction adds an immediate value to the PC value to form a PC-relative address,
4668// and writes the result to the destination register.
4669bool
4670EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4671{
4672#if 0
4673 // ARM pseudo code...
4674 if ConditionPassed() then
4675 EncodingSpecificOperations();
4676 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
4677 if d == 15 then // Can only occur for ARM encodings
4678 ALUWritePC(result);
4679 else
4680 R[d] = result;
4681#endif
4682
4683 bool success = false;
4684 const uint32_t opcode = OpcodeAsUnsigned (&success);
4685 if (!success)
4686 return false;
4687
4688 if (ConditionPassed())
4689 {
4690 uint32_t Rd;
4691 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
4692 bool add;
4693 switch (encoding)
4694 {
4695 case eEncodingT1:
4696 Rd = Bits32(opcode, 10, 8);
4697 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
4698 break;
4699 case eEncodingT2:
4700 case eEncodingT3:
4701 Rd = Bits32(opcode, 11, 8);
4702 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
4703 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
4704 if (BadReg(Rd))
4705 return false;
4706 break;
4707 case eEncodingA1:
4708 case eEncodingA2:
4709 Rd = Bits32(opcode, 15, 12);
4710 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4711 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
4712 break;
4713 default:
4714 return false;
4715 }
4716
4717 // Read the PC value.
4718 uint32_t pc = ReadCoreReg(PC_REG, &success);
4719 if (!success)
4720 return false;
4721
4722 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
4723
4724 EmulateInstruction::Context context;
4725 context.type = EmulateInstruction::eContextImmediate;
4726 context.SetNoArgs ();
4727
4728 if (!WriteCoreReg(context, result, Rd))
4729 return false;
4730 }
4731 return true;
4732}
4733
Johnny Chene97c0d52011-02-18 19:32:20 +00004734// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4735// to the destination register. It can optionally update the condition flags based on the result.
4736bool
4737EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4738{
4739#if 0
4740 // ARM pseudo code...
4741 if ConditionPassed() then
4742 EncodingSpecificOperations();
4743 result = R[n] AND imm32;
4744 if d == 15 then // Can only occur for ARM encoding
4745 ALUWritePC(result); // setflags is always FALSE here
4746 else
4747 R[d] = result;
4748 if setflags then
4749 APSR.N = result<31>;
4750 APSR.Z = IsZeroBit(result);
4751 APSR.C = carry;
4752 // APSR.V unchanged
4753#endif
4754
4755 bool success = false;
4756 const uint32_t opcode = OpcodeAsUnsigned (&success);
4757 if (!success)
4758 return false;
4759
4760 if (ConditionPassed())
4761 {
4762 uint32_t Rd, Rn;
4763 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4764 bool setflags;
4765 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4766 switch (encoding)
4767 {
4768 case eEncodingT1:
4769 Rd = Bits32(opcode, 11, 8);
4770 Rn = Bits32(opcode, 19, 16);
4771 setflags = BitIsSet(opcode, 20);
4772 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004773 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004774 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004775 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004776 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4777 return false;
4778 break;
4779 case eEncodingA1:
4780 Rd = Bits32(opcode, 15, 12);
4781 Rn = Bits32(opcode, 19, 16);
4782 setflags = BitIsSet(opcode, 20);
4783 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4784 // TODO: Emulate SUBS PC, LR and related instructions.
4785 if (Rd == 15 && setflags)
4786 return false;
4787 break;
4788 default:
4789 return false;
4790 }
4791
Johnny Chene97c0d52011-02-18 19:32:20 +00004792 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004793 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004794 if (!success)
4795 return false;
4796
4797 uint32_t result = val1 & imm32;
4798
4799 EmulateInstruction::Context context;
4800 context.type = EmulateInstruction::eContextImmediate;
4801 context.SetNoArgs ();
4802
4803 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4804 return false;
4805 }
4806 return true;
4807}
4808
4809// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4810// and writes the result to the destination register. It can optionally update the condition flags
4811// based on the result.
4812bool
4813EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4814{
4815#if 0
4816 // ARM pseudo code...
4817 if ConditionPassed() then
4818 EncodingSpecificOperations();
4819 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4820 result = R[n] AND shifted;
4821 if d == 15 then // Can only occur for ARM encoding
4822 ALUWritePC(result); // setflags is always FALSE here
4823 else
4824 R[d] = result;
4825 if setflags then
4826 APSR.N = result<31>;
4827 APSR.Z = IsZeroBit(result);
4828 APSR.C = carry;
4829 // APSR.V unchanged
4830#endif
4831
4832 bool success = false;
4833 const uint32_t opcode = OpcodeAsUnsigned (&success);
4834 if (!success)
4835 return false;
4836
4837 if (ConditionPassed())
4838 {
4839 uint32_t Rd, Rn, Rm;
4840 ARM_ShifterType shift_t;
4841 uint32_t shift_n; // the shift applied to the value read from Rm
4842 bool setflags;
4843 uint32_t carry;
4844 switch (encoding)
4845 {
4846 case eEncodingT1:
4847 Rd = Rn = Bits32(opcode, 2, 0);
4848 Rm = Bits32(opcode, 5, 3);
4849 setflags = !InITBlock();
4850 shift_t = SRType_LSL;
4851 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004852 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004853 case eEncodingT2:
4854 Rd = Bits32(opcode, 11, 8);
4855 Rn = Bits32(opcode, 19, 16);
4856 Rm = Bits32(opcode, 3, 0);
4857 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004858 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004859 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004860 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004861 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004862 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4863 return false;
4864 break;
4865 case eEncodingA1:
4866 Rd = Bits32(opcode, 15, 12);
4867 Rn = Bits32(opcode, 19, 16);
4868 Rm = Bits32(opcode, 3, 0);
4869 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004870 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004871 // TODO: Emulate SUBS PC, LR and related instructions.
4872 if (Rd == 15 && setflags)
4873 return false;
4874 break;
4875 default:
4876 return false;
4877 }
4878
Johnny Chene97c0d52011-02-18 19:32:20 +00004879 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004880 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004881 if (!success)
4882 return false;
4883
4884 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004885 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004886 if (!success)
4887 return false;
4888
4889 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4890 uint32_t result = val1 & shifted;
4891
4892 EmulateInstruction::Context context;
4893 context.type = EmulateInstruction::eContextImmediate;
4894 context.SetNoArgs ();
4895
4896 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4897 return false;
4898 }
4899 return true;
4900}
4901
Caroline Tice4d729c52011-02-18 00:55:53 +00004902// 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 +00004903// 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 +00004904bool
4905EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4906{
4907#if 0
4908 if ConditionPassed() then
4909 EncodingSpecificOperations();
4910 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4911 address = if index then offset_addr else R[n];
4912 data = MemU[address,4];
4913 if wback then R[n] = offset_addr;
4914 if t == 15 then
4915 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4916 elsif UnalignedSupport() || address<1:0> = ’00’ then
4917 R[t] = data;
4918 else // Can only apply before ARMv7
4919 R[t] = ROR(data, 8*UInt(address<1:0>));
4920#endif
4921
4922 bool success = false;
4923 const uint32_t opcode = OpcodeAsUnsigned (&success);
4924 if (!success)
4925 return false;
4926
4927 if (ConditionPassed ())
4928 {
4929 const uint32_t addr_byte_size = GetAddressByteSize();
4930
4931 uint32_t t;
4932 uint32_t n;
4933 uint32_t imm32;
4934 bool index;
4935 bool add;
4936 bool wback;
4937
4938 switch (encoding)
4939 {
4940 case eEncodingA1:
4941 // if Rn == ’1111’ then SEE LDR (literal);
4942 // if P == ’0’ && W == ’1’ then SEE LDRT;
4943 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4944 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4945 t = Bits32 (opcode, 15, 12);
4946 n = Bits32 (opcode, 19, 16);
4947 imm32 = Bits32 (opcode, 11, 0);
4948
4949 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4950 index = BitIsSet (opcode, 24);
4951 add = BitIsSet (opcode, 23);
4952 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4953
4954 // if wback && n == t then UNPREDICTABLE;
4955 if (wback && (n == t))
4956 return false;
4957
4958 break;
4959
4960 default:
4961 return false;
4962 }
4963
4964 addr_t address;
4965 addr_t offset_addr;
4966 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4967 if (!success)
4968 return false;
4969
4970 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4971 if (add)
4972 offset_addr = base_address + imm32;
4973 else
4974 offset_addr = base_address - imm32;
4975
4976 // address = if index then offset_addr else R[n];
4977 if (index)
4978 address = offset_addr;
4979 else
4980 address = base_address;
4981
4982 // data = MemU[address,4];
4983
4984 Register base_reg;
4985 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4986
4987 EmulateInstruction::Context context;
4988 context.type = eContextRegisterLoad;
4989 context.SetRegisterPlusOffset (base_reg, address - base_address);
4990
4991 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4992 if (!success)
4993 return false;
4994
4995 // if wback then R[n] = offset_addr;
4996 if (wback)
4997 {
4998 context.type = eContextAdjustBaseRegister;
4999 context.SetAddress (offset_addr);
5000 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5001 return false;
5002 }
5003
5004 // if t == 15 then
5005 if (t == 15)
5006 {
5007 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5008 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5009 {
5010 // LoadWritePC (data);
5011 context.type = eContextRegisterLoad;
5012 context.SetRegisterPlusOffset (base_reg, address - base_address);
5013 LoadWritePC (context, data);
5014 }
5015 else
5016 return false;
5017 }
5018 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5019 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5020 {
5021 // R[t] = data;
5022 context.type = eContextRegisterLoad;
5023 context.SetRegisterPlusOffset (base_reg, address - base_address);
5024 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5025 return false;
5026 }
5027 // else // Can only apply before ARMv7
5028 else
5029 {
5030 // R[t] = ROR(data, 8*UInt(address<1:0>));
5031 data = ROR (data, Bits32 (address, 1, 0));
5032 context.type = eContextRegisterLoad;
5033 context.SetImmediate (data);
5034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5035 return false;
5036 }
5037
5038 }
5039 return true;
5040}
5041
Caroline Ticefe479112011-02-18 18:52:37 +00005042// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5043// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5044bool
5045EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5046{
5047#if 0
5048 if ConditionPassed() then
5049 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5050 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5051 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5052 address = if index then offset_addr else R[n];
5053 data = MemU[address,4];
5054 if wback then R[n] = offset_addr;
5055 if t == 15 then
5056 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5057 elsif UnalignedSupport() || address<1:0> = ’00’ then
5058 R[t] = data;
5059 else // Can only apply before ARMv7
5060 if CurrentInstrSet() == InstrSet_ARM then
5061 R[t] = ROR(data, 8*UInt(address<1:0>));
5062 else
5063 R[t] = bits(32) UNKNOWN;
5064#endif
5065
5066 bool success = false;
5067 const uint32_t opcode = OpcodeAsUnsigned (&success);
5068 if (!success)
5069 return false;
5070
5071 if (ConditionPassed ())
5072 {
5073 const uint32_t addr_byte_size = GetAddressByteSize();
5074
5075 uint32_t t;
5076 uint32_t n;
5077 uint32_t m;
5078 bool index;
5079 bool add;
5080 bool wback;
5081 ARM_ShifterType shift_t;
5082 uint32_t shift_n;
5083
5084 switch (encoding)
5085 {
5086 case eEncodingT1:
5087 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5088 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5089 t = Bits32 (opcode, 2, 0);
5090 n = Bits32 (opcode, 5, 3);
5091 m = Bits32 (opcode, 8, 6);
5092
5093 // index = TRUE; add = TRUE; wback = FALSE;
5094 index = true;
5095 add = true;
5096 wback = false;
5097
5098 // (shift_t, shift_n) = (SRType_LSL, 0);
5099 shift_t = SRType_LSL;
5100 shift_n = 0;
5101
5102 break;
5103
5104 case eEncodingT2:
5105 // if Rn == ’1111’ then SEE LDR (literal);
5106 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5107 t = Bits32 (opcode, 15, 12);
5108 n = Bits32 (opcode, 19, 16);
5109 m = Bits32 (opcode, 3, 0);
5110
5111 // index = TRUE; add = TRUE; wback = FALSE;
5112 index = true;
5113 add = true;
5114 wback = false;
5115
5116 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5117 shift_t = SRType_LSL;
5118 shift_n = Bits32 (opcode, 5, 4);
5119
5120 // if BadReg(m) then UNPREDICTABLE;
5121 if (BadReg (m))
5122 return false;
5123
5124 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5125 if ((t == 15) && InITBlock() && !LastInITBlock())
5126 return false;
5127
5128 break;
5129
5130 case eEncodingA1:
5131 {
5132 // if P == ’0’ && W == ’1’ then SEE LDRT;
5133 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5134 t = Bits32 (opcode, 15, 12);
5135 n = Bits32 (opcode, 19, 16);
5136 m = Bits32 (opcode, 3, 0);
5137
5138 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5139 index = BitIsSet (opcode, 24);
5140 add = BitIsSet (opcode, 23);
5141 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5142
5143 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5144 uint32_t type = Bits32 (opcode, 6, 5);
5145 uint32_t imm5 = Bits32 (opcode, 11, 7);
5146 shift_n = DecodeImmShift (type, imm5, shift_t);
5147
5148 // if m == 15 then UNPREDICTABLE;
5149 if (m == 15)
5150 return false;
5151
5152 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5153 if (wback && ((n == 15) || (n == t)))
5154 return false;
5155 }
5156 break;
5157
5158
5159 default:
5160 return false;
5161 }
5162
5163 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5164 if (!success)
5165 return false;
5166
5167 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5168 if (!success)
5169 return false;
5170
5171 addr_t offset_addr;
5172 addr_t address;
5173
5174 // 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 +00005175 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005176
5177 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5178 if (add)
5179 offset_addr = Rn + offset;
5180 else
5181 offset_addr = Rn - offset;
5182
5183 // address = if index then offset_addr else R[n];
5184 if (index)
5185 address = offset_addr;
5186 else
5187 address = Rn;
5188
5189 // data = MemU[address,4];
5190 Register base_reg;
5191 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5192
5193 EmulateInstruction::Context context;
5194 context.type = eContextRegisterLoad;
5195 context.SetRegisterPlusOffset (base_reg, address - Rn);
5196
5197 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5198 if (!success)
5199 return false;
5200
5201 // if wback then R[n] = offset_addr;
5202 if (wback)
5203 {
5204 context.type = eContextAdjustBaseRegister;
5205 context.SetAddress (offset_addr);
5206 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5207 return false;
5208 }
5209
5210 // if t == 15 then
5211 if (t == 15)
5212 {
5213 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5214 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5215 {
5216 context.type = eContextRegisterLoad;
5217 context.SetRegisterPlusOffset (base_reg, address - Rn);
5218 LoadWritePC (context, data);
5219 }
5220 else
5221 return false;
5222 }
5223 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5224 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5225 {
5226 // R[t] = data;
5227 context.type = eContextRegisterLoad;
5228 context.SetRegisterPlusOffset (base_reg, address - Rn);
5229 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5230 return false;
5231 }
5232 else // Can only apply before ARMv7
5233 {
5234 // if CurrentInstrSet() == InstrSet_ARM then
5235 if (CurrentInstrSet () == eModeARM)
5236 {
5237 // R[t] = ROR(data, 8*UInt(address<1:0>));
5238 data = ROR (data, Bits32 (address, 1, 0));
5239 context.type = eContextRegisterLoad;
5240 context.SetImmediate (data);
5241 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5242 return false;
5243 }
5244 else
5245 {
5246 // R[t] = bits(32) UNKNOWN;
5247 WriteBits32Unknown (t);
5248 }
5249 }
5250 }
5251 return true;
5252}
Caroline Tice21b604b2011-02-18 21:06:04 +00005253
5254// LDRB (immediate, Thumb)
5255bool
5256EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5257{
5258#if 0
5259 if ConditionPassed() then
5260 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5261 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5262 address = if index then offset_addr else R[n];
5263 R[t] = ZeroExtend(MemU[address,1], 32);
5264 if wback then R[n] = offset_addr;
5265#endif
5266
5267 bool success = false;
5268 const uint32_t opcode = OpcodeAsUnsigned (&success);
5269 if (!success)
5270 return false;
5271
5272 if (ConditionPassed ())
5273 {
5274 uint32_t t;
5275 uint32_t n;
5276 uint32_t imm32;
5277 bool index;
5278 bool add;
5279 bool wback;
5280
5281 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5282 switch (encoding)
5283 {
5284 case eEncodingT1:
5285 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5286 t = Bits32 (opcode, 2, 0);
5287 n = Bits32 (opcode, 5, 3);
5288 imm32 = Bits32 (opcode, 10, 6);
5289
5290 // index = TRUE; add = TRUE; wback = FALSE;
5291 index = true;
5292 add = true;
5293 wback= false;
5294
5295 break;
5296
5297 case eEncodingT2:
5298 // if Rt == ’1111’ then SEE PLD;
5299 // if Rn == ’1111’ then SEE LDRB (literal);
5300 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5301 t = Bits32 (opcode, 15, 12);
5302 n = Bits32 (opcode, 19, 16);
5303 imm32 = Bits32 (opcode, 11, 0);
5304
5305 // index = TRUE; add = TRUE; wback = FALSE;
5306 index = true;
5307 add = true;
5308 wback = false;
5309
5310 // if t == 13 then UNPREDICTABLE;
5311 if (t == 13)
5312 return false;
5313
5314 break;
5315
5316 case eEncodingT3:
5317 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5318 // if Rn == ’1111’ then SEE LDRB (literal);
5319 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5320 // if P == ’0’ && W == ’0’ then UNDEFINED;
5321 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5322 return false;
5323
5324 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5325 t = Bits32 (opcode, 15, 12);
5326 n = Bits32 (opcode, 19, 16);
5327 imm32 = Bits32 (opcode, 7, 0);
5328
5329 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5330 index = BitIsSet (opcode, 10);
5331 add = BitIsSet (opcode, 9);
5332 wback = BitIsSet (opcode, 8);
5333
5334 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5335 if (BadReg (t) || (wback && (n == t)))
5336 return false;
5337
5338 break;
5339
5340 default:
5341 return false;
5342 }
5343
5344 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5345 if (!success)
5346 return false;
5347
5348 addr_t address;
5349 addr_t offset_addr;
5350
5351 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5352 if (add)
5353 offset_addr = Rn + imm32;
5354 else
5355 offset_addr = Rn - imm32;
5356
5357 // address = if index then offset_addr else R[n];
5358 if (index)
5359 address = offset_addr;
5360 else
5361 address = Rn;
5362
5363 // R[t] = ZeroExtend(MemU[address,1], 32);
5364 Register base_reg;
5365 Register data_reg;
5366 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5367 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5368
5369 EmulateInstruction::Context context;
5370 context.type = eContextRegisterLoad;
5371 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5372
5373 uint64_t data = MemURead (context, address, 1, 0, &success);
5374 if (!success)
5375 return false;
5376
5377 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5378 return false;
5379
5380 // if wback then R[n] = offset_addr;
5381 if (wback)
5382 {
5383 context.type = eContextAdjustBaseRegister;
5384 context.SetAddress (offset_addr);
5385 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5386 return false;
5387 }
5388 }
5389 return true;
5390}
Caroline Ticef55261f2011-02-18 22:24:22 +00005391
5392// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5393// zero-extends it to form a 32-bit word and writes it to a register.
5394bool
5395EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5396{
5397#if 0
5398 if ConditionPassed() then
5399 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5400 base = Align(PC,4);
5401 address = if add then (base + imm32) else (base - imm32);
5402 R[t] = ZeroExtend(MemU[address,1], 32);
5403#endif
5404
5405 bool success = false;
5406 const uint32_t opcode = OpcodeAsUnsigned (&success);
5407 if (!success)
5408 return false;
5409
5410 if (ConditionPassed ())
5411 {
5412 uint32_t t;
5413 uint32_t imm32;
5414 bool add;
5415 switch (encoding)
5416 {
5417 case eEncodingT1:
5418 // if Rt == ’1111’ then SEE PLD;
5419 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5420 t = Bits32 (opcode, 15, 12);
5421 imm32 = Bits32 (opcode, 11, 0);
5422 add = BitIsSet (opcode, 23);
5423
5424 // if t == 13 then UNPREDICTABLE;
5425 if (t == 13)
5426 return false;
5427
5428 break;
5429
5430 case eEncodingA1:
5431 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5432 t = Bits32 (opcode, 15, 12);
5433 imm32 = Bits32 (opcode, 11, 0);
5434 add = BitIsSet (opcode, 23);
5435
5436 // if t == 15 then UNPREDICTABLE;
5437 if (t == 15)
5438 return false;
5439 break;
5440
5441 default:
5442 return false;
5443 }
5444
5445 // base = Align(PC,4);
5446 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5447 if (!success)
5448 return false;
5449
5450 uint32_t base = AlignPC (pc_val);
5451
5452 addr_t address;
5453 // address = if add then (base + imm32) else (base - imm32);
5454 if (add)
5455 address = base + imm32;
5456 else
5457 address = base - imm32;
5458
5459 // R[t] = ZeroExtend(MemU[address,1], 32);
5460 EmulateInstruction::Context context;
5461 context.type = eContextRelativeBranchImmediate;
5462 context.SetImmediate (address - base);
5463
5464 uint64_t data = MemURead (context, address, 1, 0, &success);
5465 if (!success)
5466 return false;
5467
5468 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5469 return false;
5470 }
5471 return true;
5472}
Caroline Tice30fec122011-02-18 23:52:21 +00005473
5474// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5475// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5476// optionally be shifted.
5477bool
5478EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5479{
5480#if 0
5481 if ConditionPassed() then
5482 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5483 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5484 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5485 address = if index then offset_addr else R[n];
5486 R[t] = ZeroExtend(MemU[address,1],32);
5487 if wback then R[n] = offset_addr;
5488#endif
5489
5490 bool success = false;
5491 const uint32_t opcode = OpcodeAsUnsigned (&success);
5492 if (!success)
5493 return false;
5494
5495 if (ConditionPassed ())
5496 {
5497 uint32_t t;
5498 uint32_t n;
5499 uint32_t m;
5500 bool index;
5501 bool add;
5502 bool wback;
5503 ARM_ShifterType shift_t;
5504 uint32_t shift_n;
5505
5506 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5507 switch (encoding)
5508 {
5509 case eEncodingT1:
5510 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5511 t = Bits32 (opcode, 2, 0);
5512 n = Bits32 (opcode, 5, 3);
5513 m = Bits32 (opcode, 8, 6);
5514
5515 // index = TRUE; add = TRUE; wback = FALSE;
5516 index = true;
5517 add = true;
5518 wback = false;
5519
5520 // (shift_t, shift_n) = (SRType_LSL, 0);
5521 shift_t = SRType_LSL;
5522 shift_n = 0;
5523 break;
5524
5525 case eEncodingT2:
5526 // if Rt == ’1111’ then SEE PLD;
5527 // if Rn == ’1111’ then SEE LDRB (literal);
5528 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5529 t = Bits32 (opcode, 15, 12);
5530 n = Bits32 (opcode, 19, 16);
5531 m = Bits32 (opcode, 3, 0);
5532
5533 // index = TRUE; add = TRUE; wback = FALSE;
5534 index = true;
5535 add = true;
5536 wback = false;
5537
5538 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5539 shift_t = SRType_LSL;
5540 shift_n = Bits32 (opcode, 5, 4);
5541
5542 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5543 if ((t == 13) || BadReg (m))
5544 return false;
5545 break;
5546
5547 case eEncodingA1:
5548 {
5549 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5550 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5551 t = Bits32 (opcode, 15, 12);
5552 n = Bits32 (opcode, 19, 16);
5553 m = Bits32 (opcode, 3, 0);
5554
5555 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5556 index = BitIsSet (opcode, 24);
5557 add = BitIsSet (opcode, 23);
5558 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5559
5560 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5561 uint32_t type = Bits32 (opcode, 6, 5);
5562 uint32_t imm5 = Bits32 (opcode, 11, 7);
5563 shift_n = DecodeImmShift (type, imm5, shift_t);
5564
5565 // if t == 15 || m == 15 then UNPREDICTABLE;
5566 if ((t == 15) || (m == 15))
5567 return false;
5568
5569 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5570 if (wback && ((n == 15) || (n == t)))
5571 return false;
5572 }
5573 break;
5574
5575 default:
5576 return false;
5577 }
5578
5579 addr_t offset_addr;
5580 addr_t address;
5581
5582 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5583 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5584 if (!success)
5585 return false;
5586
5587 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5588
5589 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5590 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5591 if (!success)
5592 return false;
5593
5594 if (add)
5595 offset_addr = Rn + offset;
5596 else
5597 offset_addr = Rn - offset;
5598
5599 // address = if index then offset_addr else R[n];
5600 if (index)
5601 address = offset_addr;
5602 else
5603 address = Rn;
5604
5605 // R[t] = ZeroExtend(MemU[address,1],32);
5606 Register base_reg;
5607 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5608
5609 EmulateInstruction::Context context;
5610 context.type = eContextRegisterLoad;
5611 context.SetRegisterPlusOffset (base_reg, address - Rn);
5612
5613 uint64_t data = MemURead (context, address, 1, 0, &success);
5614 if (!success)
5615 return false;
5616
5617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5618 return false;
5619
5620 // if wback then R[n] = offset_addr;
5621 if (wback)
5622 {
5623 context.type = eContextAdjustBaseRegister;
5624 context.SetAddress (offset_addr);
5625 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5626 return false;
5627 }
5628 }
5629 return true;
5630}
Caroline Ticefe479112011-02-18 18:52:37 +00005631
Johnny Chen2115b412011-02-21 23:42:44 +00005632// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5633// and writes the result to the destination register. It can optionally update the condition flags based on
5634// the result.
5635bool
5636EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5637{
5638#if 0
5639 // ARM pseudo code...
5640 if ConditionPassed() then
5641 EncodingSpecificOperations();
5642 result = R[n] EOR imm32;
5643 if d == 15 then // Can only occur for ARM encoding
5644 ALUWritePC(result); // setflags is always FALSE here
5645 else
5646 R[d] = result;
5647 if setflags then
5648 APSR.N = result<31>;
5649 APSR.Z = IsZeroBit(result);
5650 APSR.C = carry;
5651 // APSR.V unchanged
5652#endif
5653
5654 bool success = false;
5655 const uint32_t opcode = OpcodeAsUnsigned (&success);
5656 if (!success)
5657 return false;
5658
5659 if (ConditionPassed())
5660 {
5661 uint32_t Rd, Rn;
5662 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5663 bool setflags;
5664 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5665 switch (encoding)
5666 {
5667 case eEncodingT1:
5668 Rd = Bits32(opcode, 11, 8);
5669 Rn = Bits32(opcode, 19, 16);
5670 setflags = BitIsSet(opcode, 20);
5671 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5672 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5673 if (Rd == 15 && setflags)
5674 return EmulateTEQImm(eEncodingT1);
5675 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5676 return false;
5677 break;
5678 case eEncodingA1:
5679 Rd = Bits32(opcode, 15, 12);
5680 Rn = Bits32(opcode, 19, 16);
5681 setflags = BitIsSet(opcode, 20);
5682 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5683 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5684 // TODO: Emulate SUBS PC, LR and related instructions.
5685 if (Rd == 15 && setflags)
5686 return false;
5687 break;
5688 default:
5689 return false;
5690 }
5691
5692 // Read the first operand.
5693 uint32_t val1 = ReadCoreReg(Rn, &success);
5694 if (!success)
5695 return false;
5696
5697 uint32_t result = val1 ^ imm32;
5698
5699 EmulateInstruction::Context context;
5700 context.type = EmulateInstruction::eContextImmediate;
5701 context.SetNoArgs ();
5702
5703 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5704 return false;
5705 }
5706 return true;
5707}
5708
5709// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5710// optionally-shifted register value, and writes the result to the destination register.
5711// It can optionally update the condition flags based on the result.
5712bool
5713EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5714{
5715#if 0
5716 // ARM pseudo code...
5717 if ConditionPassed() then
5718 EncodingSpecificOperations();
5719 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5720 result = R[n] EOR shifted;
5721 if d == 15 then // Can only occur for ARM encoding
5722 ALUWritePC(result); // setflags is always FALSE here
5723 else
5724 R[d] = result;
5725 if setflags then
5726 APSR.N = result<31>;
5727 APSR.Z = IsZeroBit(result);
5728 APSR.C = carry;
5729 // APSR.V unchanged
5730#endif
5731
5732 bool success = false;
5733 const uint32_t opcode = OpcodeAsUnsigned (&success);
5734 if (!success)
5735 return false;
5736
5737 if (ConditionPassed())
5738 {
5739 uint32_t Rd, Rn, Rm;
5740 ARM_ShifterType shift_t;
5741 uint32_t shift_n; // the shift applied to the value read from Rm
5742 bool setflags;
5743 uint32_t carry;
5744 switch (encoding)
5745 {
5746 case eEncodingT1:
5747 Rd = Rn = Bits32(opcode, 2, 0);
5748 Rm = Bits32(opcode, 5, 3);
5749 setflags = !InITBlock();
5750 shift_t = SRType_LSL;
5751 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005752 break;
Johnny Chen2115b412011-02-21 23:42:44 +00005753 case eEncodingT2:
5754 Rd = Bits32(opcode, 11, 8);
5755 Rn = Bits32(opcode, 19, 16);
5756 Rm = Bits32(opcode, 3, 0);
5757 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005758 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5759 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005760 if (Rd == 15 && setflags)
5761 return EmulateTEQReg(eEncodingT1);
5762 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5763 return false;
5764 break;
5765 case eEncodingA1:
5766 Rd = Bits32(opcode, 15, 12);
5767 Rn = Bits32(opcode, 19, 16);
5768 Rm = Bits32(opcode, 3, 0);
5769 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005770 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005771 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5772 // TODO: Emulate SUBS PC, LR and related instructions.
5773 if (Rd == 15 && setflags)
5774 return false;
5775 break;
5776 default:
5777 return false;
5778 }
5779
5780 // Read the first operand.
5781 uint32_t val1 = ReadCoreReg(Rn, &success);
5782 if (!success)
5783 return false;
5784
5785 // Read the second operand.
5786 uint32_t val2 = ReadCoreReg(Rm, &success);
5787 if (!success)
5788 return false;
5789
5790 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5791 uint32_t result = val1 ^ shifted;
5792
5793 EmulateInstruction::Context context;
5794 context.type = EmulateInstruction::eContextImmediate;
5795 context.SetNoArgs ();
5796
5797 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5798 return false;
5799 }
5800 return true;
5801}
5802
Johnny Chen7c5234d2011-02-18 23:41:11 +00005803// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5804// writes the result to the destination register. It can optionally update the condition flags based
5805// on the result.
5806bool
5807EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5808{
5809#if 0
5810 // ARM pseudo code...
5811 if ConditionPassed() then
5812 EncodingSpecificOperations();
5813 result = R[n] OR imm32;
5814 if d == 15 then // Can only occur for ARM encoding
5815 ALUWritePC(result); // setflags is always FALSE here
5816 else
5817 R[d] = result;
5818 if setflags then
5819 APSR.N = result<31>;
5820 APSR.Z = IsZeroBit(result);
5821 APSR.C = carry;
5822 // APSR.V unchanged
5823#endif
5824
5825 bool success = false;
5826 const uint32_t opcode = OpcodeAsUnsigned (&success);
5827 if (!success)
5828 return false;
5829
5830 if (ConditionPassed())
5831 {
5832 uint32_t Rd, Rn;
5833 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5834 bool setflags;
5835 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5836 switch (encoding)
5837 {
5838 case eEncodingT1:
5839 Rd = Bits32(opcode, 11, 8);
5840 Rn = Bits32(opcode, 19, 16);
5841 setflags = BitIsSet(opcode, 20);
5842 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5843 // if Rn == ‘1111’ then SEE MOV (immediate);
5844 if (Rn == 15)
5845 return EmulateMOVRdImm(eEncodingT2);
5846 if (BadReg(Rd) || Rn == 13)
5847 return false;
5848 break;
5849 case eEncodingA1:
5850 Rd = Bits32(opcode, 15, 12);
5851 Rn = Bits32(opcode, 19, 16);
5852 setflags = BitIsSet(opcode, 20);
5853 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5854 // TODO: Emulate SUBS PC, LR and related instructions.
5855 if (Rd == 15 && setflags)
5856 return false;
5857 break;
5858 default:
5859 return false;
5860 }
5861
5862 // Read the first operand.
5863 uint32_t val1 = ReadCoreReg(Rn, &success);
5864 if (!success)
5865 return false;
5866
5867 uint32_t result = val1 | imm32;
5868
5869 EmulateInstruction::Context context;
5870 context.type = EmulateInstruction::eContextImmediate;
5871 context.SetNoArgs ();
5872
5873 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5874 return false;
5875 }
5876 return true;
5877}
5878
5879// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5880// value, and writes the result to the destination register. It can optionally update the condition flags based
5881// on the result.
5882bool
5883EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5884{
5885#if 0
5886 // ARM pseudo code...
5887 if ConditionPassed() then
5888 EncodingSpecificOperations();
5889 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5890 result = R[n] OR shifted;
5891 if d == 15 then // Can only occur for ARM encoding
5892 ALUWritePC(result); // setflags is always FALSE here
5893 else
5894 R[d] = result;
5895 if setflags then
5896 APSR.N = result<31>;
5897 APSR.Z = IsZeroBit(result);
5898 APSR.C = carry;
5899 // APSR.V unchanged
5900#endif
5901
5902 bool success = false;
5903 const uint32_t opcode = OpcodeAsUnsigned (&success);
5904 if (!success)
5905 return false;
5906
5907 if (ConditionPassed())
5908 {
5909 uint32_t Rd, Rn, Rm;
5910 ARM_ShifterType shift_t;
5911 uint32_t shift_n; // the shift applied to the value read from Rm
5912 bool setflags;
5913 uint32_t carry;
5914 switch (encoding)
5915 {
5916 case eEncodingT1:
5917 Rd = Rn = Bits32(opcode, 2, 0);
5918 Rm = Bits32(opcode, 5, 3);
5919 setflags = !InITBlock();
5920 shift_t = SRType_LSL;
5921 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005922 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005923 case eEncodingT2:
5924 Rd = Bits32(opcode, 11, 8);
5925 Rn = Bits32(opcode, 19, 16);
5926 Rm = Bits32(opcode, 3, 0);
5927 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005928 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5929 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005930 if (Rn == 15)
5931 return EmulateMOVRdRm(eEncodingT3);
5932 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5933 return false;
5934 break;
5935 case eEncodingA1:
5936 Rd = Bits32(opcode, 15, 12);
5937 Rn = Bits32(opcode, 19, 16);
5938 Rm = Bits32(opcode, 3, 0);
5939 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005940 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005941 // TODO: Emulate SUBS PC, LR and related instructions.
5942 if (Rd == 15 && setflags)
5943 return false;
5944 break;
5945 default:
5946 return false;
5947 }
5948
5949 // Read the first operand.
5950 uint32_t val1 = ReadCoreReg(Rn, &success);
5951 if (!success)
5952 return false;
5953
5954 // Read the second operand.
5955 uint32_t val2 = ReadCoreReg(Rm, &success);
5956 if (!success)
5957 return false;
5958
5959 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005960 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005961
5962 EmulateInstruction::Context context;
5963 context.type = EmulateInstruction::eContextImmediate;
5964 context.SetNoArgs ();
5965
5966 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5967 return false;
5968 }
5969 return true;
5970}
5971
Johnny Chened32e7c2011-02-22 23:42:58 +00005972// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
5973// the destination register. It can optionally update the condition flags based on the result.
5974bool
5975EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
5976{
5977#if 0
5978 // ARM pseudo code...
5979 if ConditionPassed() then
5980 EncodingSpecificOperations();
5981 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
5982 if d == 15 then // Can only occur for ARM encoding
5983 ALUWritePC(result); // setflags is always FALSE here
5984 else
5985 R[d] = result;
5986 if setflags then
5987 APSR.N = result<31>;
5988 APSR.Z = IsZeroBit(result);
5989 APSR.C = carry;
5990 APSR.V = overflow;
5991#endif
5992
5993 bool success = false;
5994 const uint32_t opcode = OpcodeAsUnsigned (&success);
5995 if (!success)
5996 return false;
5997
5998 uint32_t Rd; // the destination register
5999 uint32_t Rn; // the first operand
6000 bool setflags;
6001 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6002 switch (encoding) {
6003 case eEncodingT1:
6004 Rd = Bits32(opcode, 2, 0);
6005 Rn = Bits32(opcode, 5, 3);
6006 setflags = !InITBlock();
6007 imm32 = 0;
6008 break;
6009 case eEncodingT2:
6010 Rd = Bits32(opcode, 11, 8);
6011 Rn = Bits32(opcode, 19, 16);
6012 setflags = BitIsSet(opcode, 20);
6013 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6014 if (BadReg(Rd) || BadReg(Rn))
6015 return false;
6016 break;
6017 case eEncodingA1:
6018 Rd = Bits32(opcode, 15, 12);
6019 Rn = Bits32(opcode, 19, 16);
6020 setflags = BitIsSet(opcode, 20);
6021 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6022 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6023 // TODO: Emulate SUBS PC, LR and related instructions.
6024 if (Rd == 15 && setflags)
6025 return false;
6026 break;
6027 default:
6028 return false;
6029 }
6030 // Read the register value from the operand register Rn.
6031 uint32_t reg_val = ReadCoreReg(Rn, &success);
6032 if (!success)
6033 return false;
6034
6035 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
6036
6037 EmulateInstruction::Context context;
6038 context.type = EmulateInstruction::eContextImmediate;
6039 context.SetNoArgs ();
6040
6041 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6042 return false;
6043
6044 return true;
6045}
6046
6047// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
6048// result to the destination register. It can optionally update the condition flags based on the result.
6049bool
6050EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
6051{
6052#if 0
6053 // ARM pseudo code...
6054 if ConditionPassed() then
6055 EncodingSpecificOperations();
6056 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6057 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
6058 if d == 15 then // Can only occur for ARM encoding
6059 ALUWritePC(result); // setflags is always FALSE here
6060 else
6061 R[d] = result;
6062 if setflags then
6063 APSR.N = result<31>;
6064 APSR.Z = IsZeroBit(result);
6065 APSR.C = carry;
6066 APSR.V = overflow;
6067#endif
6068
6069 bool success = false;
6070 const uint32_t opcode = OpcodeAsUnsigned (&success);
6071 if (!success)
6072 return false;
6073
6074 uint32_t Rd; // the destination register
6075 uint32_t Rn; // the first operand
6076 uint32_t Rm; // the second operand
6077 bool setflags;
6078 ARM_ShifterType shift_t;
6079 uint32_t shift_n; // the shift applied to the value read from Rm
6080 switch (encoding) {
6081 case eEncodingT1:
6082 Rd = Bits32(opcode, 11, 8);
6083 Rn = Bits32(opcode, 19, 16);
6084 Rm = Bits32(opcode, 3, 0);
6085 setflags = BitIsSet(opcode, 20);
6086 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6087 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6088 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6089 return false;
6090 break;
6091 case eEncodingA1:
6092 Rd = Bits32(opcode, 15, 12);
6093 Rn = Bits32(opcode, 19, 16);
6094 Rm = Bits32(opcode, 3, 0);
6095 setflags = BitIsSet(opcode, 20);
6096 shift_n = DecodeImmShiftARM(opcode, shift_t);
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 register Rn.
6106 uint32_t val1 = ReadCoreReg(Rn, &success);
6107 if (!success)
6108 return false;
6109
6110 // Read the register value from register Rm.
6111 uint32_t val2 = ReadCoreReg(Rm, &success);
6112 if (!success)
6113 return false;
6114
6115 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6116 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6117
6118 EmulateInstruction::Context context;
6119 context.type = EmulateInstruction::eContextImmediate;
6120 context.SetNoArgs();
6121 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6122 return false;
6123
6124 return true;
6125}
6126
Johnny Chen90e607b2011-02-23 00:07:09 +00006127// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
6128// an immediate value, and writes the result to the destination register. It can optionally update the condition
6129// flags based on the result.
6130bool
6131EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
6132{
6133#if 0
6134 // ARM pseudo code...
6135 if ConditionPassed() then
6136 EncodingSpecificOperations();
6137 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
6138 if d == 15 then
6139 ALUWritePC(result); // setflags is always FALSE here
6140 else
6141 R[d] = result;
6142 if setflags then
6143 APSR.N = result<31>;
6144 APSR.Z = IsZeroBit(result);
6145 APSR.C = carry;
6146 APSR.V = overflow;
6147#endif
6148
6149 bool success = false;
6150 const uint32_t opcode = OpcodeAsUnsigned (&success);
6151 if (!success)
6152 return false;
6153
6154 uint32_t Rd; // the destination register
6155 uint32_t Rn; // the first operand
6156 bool setflags;
6157 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6158 switch (encoding) {
6159 case eEncodingA1:
6160 Rd = Bits32(opcode, 15, 12);
6161 Rn = Bits32(opcode, 19, 16);
6162 setflags = BitIsSet(opcode, 20);
6163 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6164 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6165 // TODO: Emulate SUBS PC, LR and related instructions.
6166 if (Rd == 15 && setflags)
6167 return false;
6168 break;
6169 default:
6170 return false;
6171 }
6172 // Read the register value from the operand register Rn.
6173 uint32_t reg_val = ReadCoreReg(Rn, &success);
6174 if (!success)
6175 return false;
6176
6177 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
6178
6179 EmulateInstruction::Context context;
6180 context.type = EmulateInstruction::eContextImmediate;
6181 context.SetNoArgs ();
6182
6183 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6184 return false;
6185
6186 return true;
6187}
6188
6189// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
6190// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
6191// condition flags based on the result.
6192bool
6193EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
6194{
6195#if 0
6196 // ARM pseudo code...
6197 if ConditionPassed() then
6198 EncodingSpecificOperations();
6199 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6200 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
6201 if d == 15 then
6202 ALUWritePC(result); // setflags is always FALSE here
6203 else
6204 R[d] = result;
6205 if setflags then
6206 APSR.N = result<31>;
6207 APSR.Z = IsZeroBit(result);
6208 APSR.C = carry;
6209 APSR.V = overflow;
6210#endif
6211
6212 bool success = false;
6213 const uint32_t opcode = OpcodeAsUnsigned (&success);
6214 if (!success)
6215 return false;
6216
6217 uint32_t Rd; // the destination register
6218 uint32_t Rn; // the first operand
6219 uint32_t Rm; // the second operand
6220 bool setflags;
6221 ARM_ShifterType shift_t;
6222 uint32_t shift_n; // the shift applied to the value read from Rm
6223 switch (encoding) {
6224 case eEncodingA1:
6225 Rd = Bits32(opcode, 15, 12);
6226 Rn = Bits32(opcode, 19, 16);
6227 Rm = Bits32(opcode, 3, 0);
6228 setflags = BitIsSet(opcode, 20);
6229 shift_n = DecodeImmShiftARM(opcode, shift_t);
6230 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6231 // TODO: Emulate SUBS PC, LR and related instructions.
6232 if (Rd == 15 && setflags)
6233 return false;
6234 break;
6235 default:
6236 return false;
6237 }
6238 // Read the register value from register Rn.
6239 uint32_t val1 = ReadCoreReg(Rn, &success);
6240 if (!success)
6241 return false;
6242
6243 // Read the register value from register Rm.
6244 uint32_t val2 = ReadCoreReg(Rm, &success);
6245 if (!success)
6246 return false;
6247
6248 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6249 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
6250
6251 EmulateInstruction::Context context;
6252 context.type = EmulateInstruction::eContextImmediate;
6253 context.SetNoArgs();
6254 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6255 return false;
6256
6257 return true;
6258}
6259
Johnny Chen9b381772011-02-23 01:01:21 +00006260// Subtract with Carry (immediate) subtracts an immediate value and the value of
6261// NOT (Carry flag) from a register value, and writes the result to the destination register.
6262// It can optionally update the condition flags based on the result.
6263bool
6264EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
6265{
6266#if 0
6267 // ARM pseudo code...
6268 if ConditionPassed() then
6269 EncodingSpecificOperations();
6270 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
6271 if d == 15 then // Can only occur for ARM encoding
6272 ALUWritePC(result); // setflags is always FALSE here
6273 else
6274 R[d] = result;
6275 if setflags then
6276 APSR.N = result<31>;
6277 APSR.Z = IsZeroBit(result);
6278 APSR.C = carry;
6279 APSR.V = overflow;
6280#endif
6281
6282 bool success = false;
6283 const uint32_t opcode = OpcodeAsUnsigned (&success);
6284 if (!success)
6285 return false;
6286
6287 uint32_t Rd; // the destination register
6288 uint32_t Rn; // the first operand
6289 bool setflags;
6290 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6291 switch (encoding) {
6292 case eEncodingT1:
6293 Rd = Bits32(opcode, 11, 8);
6294 Rn = Bits32(opcode, 19, 16);
6295 setflags = BitIsSet(opcode, 20);
6296 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6297 if (BadReg(Rd) || BadReg(Rn))
6298 return false;
6299 break;
6300 case eEncodingA1:
6301 Rd = Bits32(opcode, 15, 12);
6302 Rn = Bits32(opcode, 19, 16);
6303 setflags = BitIsSet(opcode, 20);
6304 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6305 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6306 // TODO: Emulate SUBS PC, LR and related instructions.
6307 if (Rd == 15 && setflags)
6308 return false;
6309 break;
6310 default:
6311 return false;
6312 }
6313 // Read the register value from the operand register Rn.
6314 uint32_t reg_val = ReadCoreReg(Rn, &success);
6315 if (!success)
6316 return false;
6317
6318 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
6319
6320 EmulateInstruction::Context context;
6321 context.type = EmulateInstruction::eContextImmediate;
6322 context.SetNoArgs ();
6323
6324 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6325 return false;
6326
6327 return true;
6328}
6329
6330// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
6331// NOT (Carry flag) from a register value, and writes the result to the destination register.
6332// It can optionally update the condition flags based on the result.
6333bool
6334EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
6335{
6336#if 0
6337 // ARM pseudo code...
6338 if ConditionPassed() then
6339 EncodingSpecificOperations();
6340 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6341 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
6342 if d == 15 then // Can only occur for ARM encoding
6343 ALUWritePC(result); // setflags is always FALSE here
6344 else
6345 R[d] = result;
6346 if setflags then
6347 APSR.N = result<31>;
6348 APSR.Z = IsZeroBit(result);
6349 APSR.C = carry;
6350 APSR.V = overflow;
6351#endif
6352
6353 bool success = false;
6354 const uint32_t opcode = OpcodeAsUnsigned (&success);
6355 if (!success)
6356 return false;
6357
6358 uint32_t Rd; // the destination register
6359 uint32_t Rn; // the first operand
6360 uint32_t Rm; // the second operand
6361 bool setflags;
6362 ARM_ShifterType shift_t;
6363 uint32_t shift_n; // the shift applied to the value read from Rm
6364 switch (encoding) {
6365 case eEncodingT1:
6366 Rd = Rn = Bits32(opcode, 2, 0);
6367 Rm = Bits32(opcode, 5, 3);
6368 setflags = !InITBlock();
6369 shift_t = SRType_LSL;
6370 shift_n = 0;
6371 break;
6372 case eEncodingT2:
6373 Rd = Bits32(opcode, 11, 8);
6374 Rn = Bits32(opcode, 19, 16);
6375 Rm = Bits32(opcode, 3, 0);
6376 setflags = BitIsSet(opcode, 20);
6377 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6378 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6379 return false;
6380 break;
6381 case eEncodingA1:
6382 Rd = Bits32(opcode, 15, 12);
6383 Rn = Bits32(opcode, 19, 16);
6384 Rm = Bits32(opcode, 3, 0);
6385 setflags = BitIsSet(opcode, 20);
6386 shift_n = DecodeImmShiftARM(opcode, shift_t);
6387 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6388 // TODO: Emulate SUBS PC, LR and related instructions.
6389 if (Rd == 15 && setflags)
6390 return false;
6391 break;
6392 default:
6393 return false;
6394 }
6395 // Read the register value from register Rn.
6396 uint32_t val1 = ReadCoreReg(Rn, &success);
6397 if (!success)
6398 return false;
6399
6400 // Read the register value from register Rm.
6401 uint32_t val2 = ReadCoreReg(Rm, &success);
6402 if (!success)
6403 return false;
6404
6405 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6406 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
6407
6408 EmulateInstruction::Context context;
6409 context.type = EmulateInstruction::eContextImmediate;
6410 context.SetNoArgs();
6411 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6412 return false;
6413
6414 return true;
6415}
6416
Johnny Chen2115b412011-02-21 23:42:44 +00006417// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
6418// immediate value. It updates the condition flags based on the result, and discards the result.
6419bool
6420EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
6421{
6422#if 0
6423 // ARM pseudo code...
6424 if ConditionPassed() then
6425 EncodingSpecificOperations();
6426 result = R[n] EOR imm32;
6427 APSR.N = result<31>;
6428 APSR.Z = IsZeroBit(result);
6429 APSR.C = carry;
6430 // APSR.V unchanged
6431#endif
6432
6433 bool success = false;
6434 const uint32_t opcode = OpcodeAsUnsigned (&success);
6435 if (!success)
6436 return false;
6437
6438 if (ConditionPassed())
6439 {
6440 uint32_t Rn;
6441 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6442 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6443 switch (encoding)
6444 {
6445 case eEncodingT1:
6446 Rn = Bits32(opcode, 19, 16);
6447 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6448 if (BadReg(Rn))
6449 return false;
6450 break;
6451 case eEncodingA1:
6452 Rn = Bits32(opcode, 19, 16);
6453 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6454 break;
6455 default:
6456 return false;
6457 }
6458
6459 // Read the first operand.
6460 uint32_t val1 = ReadCoreReg(Rn, &success);
6461 if (!success)
6462 return false;
6463
6464 uint32_t result = val1 ^ imm32;
6465
6466 EmulateInstruction::Context context;
6467 context.type = EmulateInstruction::eContextImmediate;
6468 context.SetNoArgs ();
6469
6470 if (!WriteFlags(context, result, carry))
6471 return false;
6472 }
6473 return true;
6474}
6475
6476// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
6477// optionally-shifted register value. It updates the condition flags based on the result, and discards
6478// the result.
6479bool
6480EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
6481{
6482#if 0
6483 // ARM pseudo code...
6484 if ConditionPassed() then
6485 EncodingSpecificOperations();
6486 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6487 result = R[n] EOR shifted;
6488 APSR.N = result<31>;
6489 APSR.Z = IsZeroBit(result);
6490 APSR.C = carry;
6491 // APSR.V unchanged
6492#endif
6493
6494 bool success = false;
6495 const uint32_t opcode = OpcodeAsUnsigned (&success);
6496 if (!success)
6497 return false;
6498
6499 if (ConditionPassed())
6500 {
6501 uint32_t Rn, Rm;
6502 ARM_ShifterType shift_t;
6503 uint32_t shift_n; // the shift applied to the value read from Rm
6504 uint32_t carry;
6505 switch (encoding)
6506 {
6507 case eEncodingT1:
6508 Rn = Bits32(opcode, 19, 16);
6509 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006510 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006511 if (BadReg(Rn) || BadReg(Rm))
6512 return false;
6513 break;
6514 case eEncodingA1:
6515 Rn = Bits32(opcode, 19, 16);
6516 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006517 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006518 break;
6519 default:
6520 return false;
6521 }
6522
6523 // Read the first operand.
6524 uint32_t val1 = ReadCoreReg(Rn, &success);
6525 if (!success)
6526 return false;
6527
6528 // Read the second operand.
6529 uint32_t val2 = ReadCoreReg(Rm, &success);
6530 if (!success)
6531 return false;
6532
6533 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6534 uint32_t result = val1 ^ shifted;
6535
6536 EmulateInstruction::Context context;
6537 context.type = EmulateInstruction::eContextImmediate;
6538 context.SetNoArgs ();
6539
6540 if (!WriteFlags(context, result, carry))
6541 return false;
6542 }
6543 return true;
6544}
6545
Johnny Chende3cce32011-02-21 21:24:49 +00006546// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
6547// It updates the condition flags based on the result, and discards the result.
6548bool
6549EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6550{
6551#if 0
6552 // ARM pseudo code...
6553 if ConditionPassed() then
6554 EncodingSpecificOperations();
6555 result = R[n] AND imm32;
6556 APSR.N = result<31>;
6557 APSR.Z = IsZeroBit(result);
6558 APSR.C = carry;
6559 // APSR.V unchanged
6560#endif
6561
6562 bool success = false;
6563 const uint32_t opcode = OpcodeAsUnsigned (&success);
6564 if (!success)
6565 return false;
6566
6567 if (ConditionPassed())
6568 {
6569 uint32_t Rn;
6570 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6571 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6572 switch (encoding)
6573 {
6574 case eEncodingT1:
6575 Rn = Bits32(opcode, 19, 16);
6576 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6577 if (BadReg(Rn))
6578 return false;
6579 break;
6580 case eEncodingA1:
6581 Rn = Bits32(opcode, 19, 16);
6582 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6583 break;
6584 default:
6585 return false;
6586 }
6587
6588 // Read the first operand.
6589 uint32_t val1 = ReadCoreReg(Rn, &success);
6590 if (!success)
6591 return false;
6592
6593 uint32_t result = val1 & imm32;
6594
6595 EmulateInstruction::Context context;
6596 context.type = EmulateInstruction::eContextImmediate;
6597 context.SetNoArgs ();
6598
6599 if (!WriteFlags(context, result, carry))
6600 return false;
6601 }
6602 return true;
6603}
6604
6605// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6606// It updates the condition flags based on the result, and discards the result.
6607bool
6608EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6609{
6610#if 0
6611 // ARM pseudo code...
6612 if ConditionPassed() then
6613 EncodingSpecificOperations();
6614 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6615 result = R[n] AND shifted;
6616 APSR.N = result<31>;
6617 APSR.Z = IsZeroBit(result);
6618 APSR.C = carry;
6619 // APSR.V unchanged
6620#endif
6621
6622 bool success = false;
6623 const uint32_t opcode = OpcodeAsUnsigned (&success);
6624 if (!success)
6625 return false;
6626
6627 if (ConditionPassed())
6628 {
6629 uint32_t Rn, Rm;
6630 ARM_ShifterType shift_t;
6631 uint32_t shift_n; // the shift applied to the value read from Rm
6632 uint32_t carry;
6633 switch (encoding)
6634 {
6635 case eEncodingT1:
6636 Rn = Bits32(opcode, 2, 0);
6637 Rm = Bits32(opcode, 5, 3);
6638 shift_t = SRType_LSL;
6639 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006640 break;
Johnny Chende3cce32011-02-21 21:24:49 +00006641 case eEncodingT2:
6642 Rn = Bits32(opcode, 19, 16);
6643 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006644 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006645 if (BadReg(Rn) || BadReg(Rm))
6646 return false;
6647 break;
6648 case eEncodingA1:
6649 Rn = Bits32(opcode, 19, 16);
6650 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006651 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006652 break;
6653 default:
6654 return false;
6655 }
6656
6657 // Read the first operand.
6658 uint32_t val1 = ReadCoreReg(Rn, &success);
6659 if (!success)
6660 return false;
6661
6662 // Read the second operand.
6663 uint32_t val2 = ReadCoreReg(Rm, &success);
6664 if (!success)
6665 return false;
6666
6667 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6668 uint32_t result = val1 & shifted;
6669
6670 EmulateInstruction::Context context;
6671 context.type = EmulateInstruction::eContextImmediate;
6672 context.SetNoArgs ();
6673
6674 if (!WriteFlags(context, result, carry))
6675 return false;
6676 }
6677 return true;
6678}
6679
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006680EmulateInstructionARM::ARMOpcode*
6681EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006682{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006683 static ARMOpcode
6684 g_arm_opcodes[] =
6685 {
6686 //----------------------------------------------------------------------
6687 // Prologue instructions
6688 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006689
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006690 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006691 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6692 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006693
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006694 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006695 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006696 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006697 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006698 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6699 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006700 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006701
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006702 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006703 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006704
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006705 // push one register
6706 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006707 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006708
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006709 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006710 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6711 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006712
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006713 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006714 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006715 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006716
Johnny Chen9f687722011-02-18 00:02:28 +00006717 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6718 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006719 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006720 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6721
6722 //----------------------------------------------------------------------
6723 // Supervisor Call (previously Software Interrupt)
6724 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006725 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6726
6727 //----------------------------------------------------------------------
6728 // Branch instructions
6729 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006730 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006731 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6732 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6733 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6734 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006735 // for example, "bx lr"
6736 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006737
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006738 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006739 // Data-processing instructions
6740 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006741 // adc (immediate)
6742 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6743 // adc (register)
6744 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006745 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006746 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006747 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006748 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00006749 // adr
6750 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
6751 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006752 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006753 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006754 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006755 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006756 // eor (immediate)
6757 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6758 // eor (register)
6759 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006760 // orr (immediate)
6761 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6762 // orr (register)
6763 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006764 // rsb (immediate)
6765 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
6766 // rsb (register)
6767 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00006768 // rsc (immediate)
6769 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
6770 // rsc (register)
6771 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00006772 // sbc (immediate)
6773 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
6774 // sbc (register)
6775 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006776 // sub (sp minus immediate)
6777 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00006778 // teq (immediate)
6779 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6780 // teq (register)
6781 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006782 // tst (immediate)
6783 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6784 // tst (register)
6785 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6786
6787
Johnny Chend642a6a2011-02-22 01:01:03 +00006788 // mvn (immediate)
6789 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6790 // mvn (register)
6791 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006792 // cmn (immediate)
6793 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6794 // cmn (register)
6795 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006796 // cmp (immediate)
6797 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6798 // cmp (register)
6799 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006800 // asr (immediate)
6801 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006802 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006803 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006804 // lsl (immediate)
6805 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6806 // lsl (register)
6807 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6808 // lsr (immediate)
6809 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6810 // lsr (register)
6811 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006812 // rrx is a special case encoding of ror (immediate)
6813 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6814 // ror (immediate)
6815 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6816 // ror (register)
6817 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006818
6819 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006820 // Load instructions
6821 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006822 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006823 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006824 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006825 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006826 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006827 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00006828 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
6829 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00006830
6831 //----------------------------------------------------------------------
6832 // Store instructions
6833 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00006834 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006835 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00006836 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00006837 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
6838 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00006839
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006840
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006841 };
6842 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
6843
6844 for (size_t i=0; i<k_num_arm_opcodes; ++i)
6845 {
6846 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
6847 return &g_arm_opcodes[i];
6848 }
6849 return NULL;
6850}
Greg Clayton64c84432011-01-21 22:02:52 +00006851
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006852
6853EmulateInstructionARM::ARMOpcode*
6854EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00006855{
Johnny Chenfdd179e2011-01-31 20:09:28 +00006856
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006857 static ARMOpcode
6858 g_thumb_opcodes[] =
6859 {
6860 //----------------------------------------------------------------------
6861 // Prologue instructions
6862 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00006863
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006864 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006865 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6866 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
6867 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00006868
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006869 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006870 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006871 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00006872 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006873 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00006874 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00006875
Johnny Chen864a8e82011-02-18 00:07:39 +00006876 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00006877 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00006878
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006879 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006880 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006881 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00006882 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
6883 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006884
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006885 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00006886 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6887 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006888
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006889 //----------------------------------------------------------------------
6890 // Epilogue instructions
6891 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00006892
Johnny Chen864a8e82011-02-18 00:07:39 +00006893 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00006894 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6895 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
6896 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00006897 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
6898 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006899
6900 //----------------------------------------------------------------------
6901 // Supervisor Call (previously Software Interrupt)
6902 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00006903 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
6904
6905 //----------------------------------------------------------------------
6906 // If Then makes up to four following instructions conditional.
6907 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006908 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
6909
6910 //----------------------------------------------------------------------
6911 // Branch instructions
6912 //----------------------------------------------------------------------
6913 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
6914 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
6915 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00006916 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006917 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00006918 // J1 == J2 == 1
6919 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6920 // J1 == J2 == 1
6921 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6922 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006923 // for example, "bx lr"
6924 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00006925 // compare and branch
6926 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00006927 // table branch byte
6928 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
6929 // table branch halfword
6930 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006931
6932 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00006933 // Data-processing instructions
6934 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006935 // adc (immediate)
6936 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
6937 // adc (register)
6938 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
6939 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
6940 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00006941 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006942 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00006943 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00006944 // adr
6945 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
6946 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
6947 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006948 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006949 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006950 // and (register)
6951 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
6952 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006953 // eor (immediate)
6954 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
6955 // eor (register)
6956 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
6957 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006958 // orr (immediate)
6959 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
6960 // orr (register)
6961 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
6962 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00006963 // rsb (immediate)
6964 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
6965 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
6966 // rsb (register)
6967 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00006968 // sbc (immediate)
6969 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
6970 // sbc (register)
6971 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
6972 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00006973 // sub (sp minus immediate)
6974 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
6975 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00006976 // teq (immediate)
6977 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
6978 // teq (register)
6979 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006980 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00006981 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00006982 // tst (register)
6983 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
6984 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
6985
Johnny Chen7c5234d2011-02-18 23:41:11 +00006986
Johnny Chen338bf542011-02-10 19:29:03 +00006987 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00006988 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00006989 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00006990 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006991 // mov{s}<c>.w <Rd>, <Rm>
6992 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00006993 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00006994 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
6995 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00006996 // mvn (immediate)
6997 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
6998 // mvn (register)
6999 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
7000 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007001 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00007002 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007003 // cmn (register)
7004 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007005 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007006 // cmp (immediate)
7007 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007008 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007009 // cmp (register) (Rn and Rm both from r0-r7)
7010 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
7011 // cmp (register) (Rn and Rm not both from r0-r7)
7012 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007013 // asr (immediate)
7014 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00007015 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00007016 // asr (register)
7017 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
7018 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007019 // lsl (immediate)
7020 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
7021 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
7022 // lsl (register)
7023 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
7024 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
7025 // lsr (immediate)
7026 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
7027 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
7028 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00007029 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007030 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007031 // rrx is a special case encoding of ror (immediate)
7032 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
7033 // ror (immediate)
7034 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
7035 // ror (register)
7036 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
7037 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007038
7039 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007040 // Load instructions
7041 //----------------------------------------------------------------------
7042 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00007043 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00007044 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00007045 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
7046 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00007047 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00007048 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
7049 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00007050 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
7051 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
7052 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00007053 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00007054 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
7055 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00007056
7057 //----------------------------------------------------------------------
7058 // Store instructions
7059 //----------------------------------------------------------------------
7060 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007061 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00007062 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00007063 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
7064 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
7065 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
7066 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
7067 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
7068 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
7069 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
7070 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
7071 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007072 };
7073
7074 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
7075 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
7076 {
7077 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
7078 return &g_thumb_opcodes[i];
7079 }
7080 return NULL;
7081}
Greg Clayton64c84432011-01-21 22:02:52 +00007082
Greg Clayton31e2a382011-01-30 20:03:56 +00007083bool
Greg Clayton395fc332011-02-15 21:59:32 +00007084EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00007085{
7086 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00007087 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00007088 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00007089 {
Greg Clayton395fc332011-02-15 21:59:32 +00007090 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
7091 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
7092 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
7093 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
7094 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
7095 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
7096 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
7097 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
7098 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
7099 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00007100 }
7101 return m_arm_isa != 0;
7102}
7103
7104
Greg Clayton64c84432011-01-21 22:02:52 +00007105bool
7106EmulateInstructionARM::ReadInstruction ()
7107{
7108 bool success = false;
7109 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
7110 if (success)
7111 {
7112 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
7113 if (success)
7114 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00007115 Context read_inst_context;
7116 read_inst_context.type = eContextReadOpcode;
7117 read_inst_context.SetNoArgs ();
7118
Greg Clayton64c84432011-01-21 22:02:52 +00007119 if (m_inst_cpsr & MASK_CPSR_T)
7120 {
7121 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007122 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007123
7124 if (success)
7125 {
7126 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
7127 {
7128 m_inst.opcode_type = eOpcode16;
7129 m_inst.opcode.inst16 = thumb_opcode;
7130 }
7131 else
7132 {
7133 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007134 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007135 }
7136 }
7137 }
7138 else
7139 {
7140 m_inst_mode = eModeARM;
7141 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007142 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007143 }
7144 }
7145 }
7146 if (!success)
7147 {
7148 m_inst_mode = eModeInvalid;
7149 m_inst_pc = LLDB_INVALID_ADDRESS;
7150 }
7151 return success;
7152}
7153
Johnny Chenee9b1f72011-02-09 01:00:31 +00007154uint32_t
7155EmulateInstructionARM::ArchVersion ()
7156{
7157 return m_arm_isa;
7158}
7159
Greg Clayton64c84432011-01-21 22:02:52 +00007160bool
7161EmulateInstructionARM::ConditionPassed ()
7162{
7163 if (m_inst_cpsr == 0)
7164 return false;
7165
7166 const uint32_t cond = CurrentCond ();
7167
7168 if (cond == UINT32_MAX)
7169 return false;
7170
7171 bool result = false;
7172 switch (UnsignedBits(cond, 3, 1))
7173 {
7174 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
7175 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
7176 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
7177 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
7178 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
7179 case 5:
7180 {
7181 bool n = (m_inst_cpsr & MASK_CPSR_N);
7182 bool v = (m_inst_cpsr & MASK_CPSR_V);
7183 result = n == v;
7184 }
7185 break;
7186 case 6:
7187 {
7188 bool n = (m_inst_cpsr & MASK_CPSR_N);
7189 bool v = (m_inst_cpsr & MASK_CPSR_V);
7190 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
7191 }
7192 break;
7193 case 7:
7194 result = true;
7195 break;
7196 }
7197
7198 if (cond & 1)
7199 result = !result;
7200 return result;
7201}
7202
Johnny Chen9ee056b2011-02-08 00:06:35 +00007203uint32_t
7204EmulateInstructionARM::CurrentCond ()
7205{
7206 switch (m_inst_mode)
7207 {
7208 default:
7209 case eModeInvalid:
7210 break;
7211
7212 case eModeARM:
7213 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
7214
7215 case eModeThumb:
7216 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
7217 // 'cond' field of the encoding.
7218 if (m_inst.opcode_type == eOpcode16 &&
7219 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
7220 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
7221 {
7222 return Bits32(m_inst.opcode.inst16, 11, 7);
7223 }
7224 else if (m_inst.opcode_type == eOpcode32 &&
7225 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
7226 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
7227 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
7228 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
7229 {
7230 return Bits32(m_inst.opcode.inst32, 25, 22);
7231 }
7232
7233 return m_it_session.GetCond();
7234 }
7235 return UINT32_MAX; // Return invalid value
7236}
7237
Johnny Chen9ee056b2011-02-08 00:06:35 +00007238bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00007239EmulateInstructionARM::InITBlock()
7240{
7241 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
7242}
7243
7244bool
7245EmulateInstructionARM::LastInITBlock()
7246{
7247 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
7248}
7249
7250bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00007251EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
7252{
7253 addr_t target;
7254
Johnny Chenee9b1f72011-02-09 01:00:31 +00007255 // Check the current instruction set.
7256 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007257 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007258 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00007259 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007260
Johnny Chen9ee056b2011-02-08 00:06:35 +00007261 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007262 return false;
7263
7264 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007265}
7266
7267// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
7268bool
Johnny Chen668b4512011-02-15 21:08:58 +00007269EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007270{
7271 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00007272 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
7273 // we want to record it and issue a WriteRegister callback so the clients
7274 // can track the mode changes accordingly.
7275 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007276
7277 if (BitIsSet(addr, 0))
7278 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007279 if (CurrentInstrSet() != eModeThumb)
7280 {
7281 SelectInstrSet(eModeThumb);
7282 cpsr_changed = true;
7283 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007284 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00007285 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007286 }
7287 else if (BitIsClear(addr, 1))
7288 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007289 if (CurrentInstrSet() != eModeARM)
7290 {
7291 SelectInstrSet(eModeARM);
7292 cpsr_changed = true;
7293 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007294 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00007295 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007296 }
7297 else
7298 return false; // address<1:0> == '10' => UNPREDICTABLE
7299
Johnny Chen0f309db2011-02-09 19:11:32 +00007300 if (cpsr_changed)
7301 {
Johnny Chen558133b2011-02-09 23:59:17 +00007302 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00007303 return false;
7304 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007305 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007306 return false;
7307
7308 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007309}
Greg Clayton64c84432011-01-21 22:02:52 +00007310
Johnny Chenee9b1f72011-02-09 01:00:31 +00007311// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
7312bool
Johnny Chen668b4512011-02-15 21:08:58 +00007313EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00007314{
7315 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00007316 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00007317 else
7318 return BranchWritePC((const Context)context, addr);
7319}
7320
Johnny Chen26863dc2011-02-09 23:43:29 +00007321// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
7322bool
Johnny Chen668b4512011-02-15 21:08:58 +00007323EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00007324{
7325 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00007326 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00007327 else
7328 return BranchWritePC((const Context)context, addr);
7329}
7330
Johnny Chenee9b1f72011-02-09 01:00:31 +00007331EmulateInstructionARM::Mode
7332EmulateInstructionARM::CurrentInstrSet ()
7333{
7334 return m_inst_mode;
7335}
7336
7337// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00007338// ReadInstruction() is performed. This function has a side effect of updating
7339// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00007340bool
7341EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
7342{
Johnny Chen558133b2011-02-09 23:59:17 +00007343 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007344 switch (arm_or_thumb)
7345 {
7346 default:
7347 return false;
7348 eModeARM:
7349 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007350 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007351 break;
7352 eModeThumb:
7353 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00007354 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007355 break;
7356 }
7357 return true;
7358}
7359
Johnny Chenef21b592011-02-10 01:52:38 +00007360// This function returns TRUE if the processor currently provides support for
7361// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
7362// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
7363bool
7364EmulateInstructionARM::UnalignedSupport()
7365{
7366 return (ArchVersion() >= ARMv7);
7367}
7368
Johnny Chenbf6ad172011-02-11 01:29:53 +00007369// The main addition and subtraction instructions can produce status information
7370// about both unsigned carry and signed overflow conditions. This status
7371// information can be used to synthesize multi-word additions and subtractions.
7372EmulateInstructionARM::AddWithCarryResult
7373EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
7374{
7375 uint32_t result;
7376 uint8_t carry_out;
7377 uint8_t overflow;
7378
7379 uint64_t unsigned_sum = x + y + carry_in;
7380 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
7381
7382 result = UnsignedBits(unsigned_sum, 31, 0);
7383 carry_out = (result == unsigned_sum ? 0 : 1);
7384 overflow = ((int32_t)result == signed_sum ? 0 : 1);
7385
7386 AddWithCarryResult res = { result, carry_out, overflow };
7387 return res;
7388}
7389
Johnny Chen157b9592011-02-18 21:13:05 +00007390uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00007391EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00007392{
Johnny Chene39f22d2011-02-19 01:36:13 +00007393 uint32_t reg_kind, reg_num;
7394 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00007395 {
Johnny Chene39f22d2011-02-19 01:36:13 +00007396 case SP_REG:
7397 reg_kind = eRegisterKindGeneric;
7398 reg_num = LLDB_REGNUM_GENERIC_SP;
7399 break;
7400 case LR_REG:
7401 reg_kind = eRegisterKindGeneric;
7402 reg_num = LLDB_REGNUM_GENERIC_RA;
7403 break;
7404 case PC_REG:
7405 reg_kind = eRegisterKindGeneric;
7406 reg_num = LLDB_REGNUM_GENERIC_PC;
7407 break;
7408 default:
7409 if (0 <= num && num < SP_REG)
7410 {
7411 reg_kind = eRegisterKindDWARF;
7412 reg_num = dwarf_r0 + num;
7413 }
Johnny Chen157b9592011-02-18 21:13:05 +00007414 else
Johnny Chene39f22d2011-02-19 01:36:13 +00007415 {
7416 assert(0 && "Invalid register number");
7417 *success = false;
7418 return ~0u;
7419 }
7420 break;
Johnny Chen157b9592011-02-18 21:13:05 +00007421 }
Johnny Chene39f22d2011-02-19 01:36:13 +00007422
7423 // Read our register.
7424 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
7425
7426 // When executing an ARM instruction , PC reads as the address of the current
7427 // instruction plus 8.
7428 // When executing a Thumb instruction , PC reads as the address of the current
7429 // instruction plus 4.
7430 if (num == 15)
7431 {
7432 if (CurrentInstrSet() == eModeARM)
7433 val += 8;
7434 else
7435 val += 4;
7436 }
Johnny Chen157b9592011-02-18 21:13:05 +00007437
7438 return val;
7439}
7440
Johnny Chenca67d1c2011-02-17 01:35:27 +00007441// Write the result to the ARM core register Rd, and optionally update the
7442// condition flags based on the result.
7443//
7444// This helper method tries to encapsulate the following pseudocode from the
7445// ARM Architecture Reference Manual:
7446//
7447// if d == 15 then // Can only occur for encoding A1
7448// ALUWritePC(result); // setflags is always FALSE here
7449// else
7450// R[d] = result;
7451// if setflags then
7452// APSR.N = result<31>;
7453// APSR.Z = IsZeroBit(result);
7454// APSR.C = carry;
7455// // APSR.V unchanged
7456//
7457// In the above case, the API client does not pass in the overflow arg, which
7458// defaults to ~0u.
7459bool
Johnny Chen10530c22011-02-17 22:37:12 +00007460EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
7461 const uint32_t result,
7462 const uint32_t Rd,
7463 bool setflags,
7464 const uint32_t carry,
7465 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00007466{
7467 if (Rd == 15)
7468 {
7469 if (!ALUWritePC (context, result))
7470 return false;
7471 }
7472 else
7473 {
Johnny Chena695f952011-02-23 21:24:25 +00007474 uint32_t reg_kind, reg_num;
7475 switch (Rd)
7476 {
7477 case SP_REG:
7478 reg_kind = eRegisterKindGeneric;
7479 reg_num = LLDB_REGNUM_GENERIC_SP;
7480 break;
7481 case LR_REG:
7482 reg_kind = eRegisterKindGeneric;
7483 reg_num = LLDB_REGNUM_GENERIC_RA;
7484 break;
7485 default:
7486 reg_kind = eRegisterKindDWARF;
7487 reg_num = dwarf_r0 + Rd;
7488 }
7489 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00007490 return false;
7491 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00007492 return WriteFlags (context, result, carry, overflow);
7493 }
7494 return true;
7495}
7496
7497// This helper method tries to encapsulate the following pseudocode from the
7498// ARM Architecture Reference Manual:
7499//
7500// APSR.N = result<31>;
7501// APSR.Z = IsZeroBit(result);
7502// APSR.C = carry;
7503// APSR.V = overflow
7504//
7505// Default arguments can be specified for carry and overflow parameters, which means
7506// not to update the respective flags.
7507bool
7508EmulateInstructionARM::WriteFlags (Context &context,
7509 const uint32_t result,
7510 const uint32_t carry,
7511 const uint32_t overflow)
7512{
7513 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00007514 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
7515 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00007516 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007517 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00007518 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00007519 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00007520 if (m_new_inst_cpsr != m_inst_cpsr)
7521 {
7522 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
7523 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00007524 }
7525 return true;
7526}
7527
Greg Clayton64c84432011-01-21 22:02:52 +00007528bool
7529EmulateInstructionARM::EvaluateInstruction ()
7530{
Johnny Chenc315f862011-02-05 00:46:10 +00007531 // Advance the ITSTATE bits to their values for the next instruction.
7532 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
7533 m_it_session.ITAdvance();
7534
Greg Clayton64c84432011-01-21 22:02:52 +00007535 return false;
7536}