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