blob: e52fe7260e6a3770833fb3c4ac454e7580b3f1f1 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
27#define APSR_C Bit32(m_inst_cpsr, CPSR_C)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V)
29
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
132#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000133
Johnny Chen0e00af22011-02-10 19:40:42 +0000134//----------------------------------------------------------------------
135//
136// EmulateInstructionARM implementation
137//
138//----------------------------------------------------------------------
139
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000140void
141EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145void
146EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000147{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000148}
149
Caroline Ticefa172202011-02-11 22:49:54 +0000150// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
151bool
152EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
153{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000154 EmulateInstruction::Context context;
155 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
156 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000157
158 uint32_t random_data = rand ();
159 const uint32_t addr_byte_size = GetAddressByteSize();
160
Caroline Ticecc96eb52011-02-17 19:20:40 +0000161 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000162 return false;
163
164 return true;
165}
166
Caroline Tice713c2662011-02-11 17:59:55 +0000167// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
168bool
169EmulateInstructionARM::WriteBits32Unknown (int n)
170{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000171 EmulateInstruction::Context context;
172 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
173 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000174
Johnny Chen62ff6f52011-02-11 18:11:22 +0000175 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
177
178 if (!success)
179 return false;
180
181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
182 return false;
183
184 return true;
185}
186
Johnny Chen08c25e82011-01-31 18:02:28 +0000187// Push Multiple Registers stores multiple registers to the stack, storing to
188// consecutive memory locations ending just below the address in SP, and updates
189// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000190bool
Johnny Chen9f687722011-02-18 00:02:28 +0000191EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000192{
193#if 0
194 // ARM pseudo code...
195 if (ConditionPassed())
196 {
197 EncodingSpecificOperations();
198 NullCheckIfThumbEE(13);
199 address = SP - 4*BitCount(registers);
200
201 for (i = 0 to 14)
202 {
203 if (registers<i> == ’1’)
204 {
205 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
206 MemA[address,4] = bits(32) UNKNOWN;
207 else
208 MemA[address,4] = R[i];
209 address = address + 4;
210 }
211 }
212
213 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
214 MemA[address,4] = PCStoreValue();
215
216 SP = SP - 4*BitCount(registers);
217 }
218#endif
219
220 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000221 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000222 if (!success)
223 return false;
224
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000226 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000228 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000229 if (!success)
230 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000232 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000235 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000237 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000238 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000239 // if BitCount(registers) < 1 then UNPREDICTABLE;
240 if (BitCount(registers) < 1)
241 return false;
242 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000243 case eEncodingT2:
244 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000245 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000246 // if BitCount(registers) < 2 then UNPREDICTABLE;
247 if (BitCount(registers) < 2)
248 return false;
249 break;
250 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000251 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000257 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000258 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000259 // Instead of return false, let's handle the following case as well,
260 // which amounts to pushing one reg onto the full descending stacks.
261 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000262 break;
263 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000264 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000265 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000270 default:
271 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000272 }
Johnny Chence1ca772011-01-25 01:13:00 +0000273 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000274 addr_t addr = sp - sp_offset;
275 uint32_t i;
276
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000277 EmulateInstruction::Context context;
278 context.type = EmulateInstruction::eContextPushRegisterOnStack;
279 Register dwarf_reg;
280 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000281 for (i=0; i<15; ++i)
282 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000283 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000285 dwarf_reg.num = dwarf_r0 + i;
286 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000290 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000291 return false;
292 addr += addr_byte_size;
293 }
294 }
295
Johnny Chen7c1bf922011-02-08 23:49:37 +0000296 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000297 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000298 dwarf_reg.num = dwarf_pc;
299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000300 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000301 if (!success)
302 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000303 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000304 return false;
305 }
306
307 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000308 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000309
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000311 return false;
312 }
313 return true;
314}
315
Johnny Chenef85e912011-01-31 23:07:40 +0000316// Pop Multiple Registers loads multiple registers from the stack, loading from
317// consecutive memory locations staring at the address in SP, and updates
318// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319bool
Johnny Chen9f687722011-02-18 00:02:28 +0000320EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000321{
322#if 0
323 // ARM pseudo code...
324 if (ConditionPassed())
325 {
326 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
327 address = SP;
328 for i = 0 to 14
329 if registers<i> == ‘1’ then
330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
331 if registers<15> == ‘1’ then
332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
336 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
337 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
338 }
339#endif
340
341 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000342 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000343 if (!success)
344 return false;
345
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000347 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000349 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000350 if (!success)
351 return false;
352 uint32_t registers = 0;
353 uint32_t Rt; // the destination register
354 switch (encoding) {
355 case eEncodingT1:
356 registers = Bits32(opcode, 7, 0);
357 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000358 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000359 registers |= (1u << 15);
360 // if BitCount(registers) < 1 then UNPREDICTABLE;
361 if (BitCount(registers) < 1)
362 return false;
363 break;
364 case eEncodingT2:
365 // Ignore bit 13.
366 registers = Bits32(opcode, 15, 0) & ~0x2000;
367 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000368 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000369 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000370 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
371 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
372 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000373 break;
374 case eEncodingT3:
375 Rt = Bits32(opcode, 15, 12);
376 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000377 if (Rt == 13)
378 return false;
379 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000380 return false;
381 registers = (1u << Rt);
382 break;
383 case eEncodingA1:
384 registers = Bits32(opcode, 15, 0);
385 // Instead of return false, let's handle the following case as well,
386 // which amounts to popping one reg from the full descending stacks.
387 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
388
389 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000390 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000391 return false;
392 break;
393 case eEncodingA2:
394 Rt = Bits32(opcode, 15, 12);
395 // if t == 13 then UNPREDICTABLE;
396 if (Rt == dwarf_sp)
397 return false;
398 registers = (1u << Rt);
399 break;
400 default:
401 return false;
402 }
403 addr_t sp_offset = addr_byte_size * BitCount (registers);
404 addr_t addr = sp;
405 uint32_t i, data;
406
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000407 EmulateInstruction::Context context;
408 context.type = EmulateInstruction::eContextPopRegisterOffStack;
409 Register dwarf_reg;
410 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000411 for (i=0; i<15; ++i)
412 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000413 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 dwarf_reg.num = dwarf_r0 + i;
416 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000417 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000418 if (!success)
419 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 return false;
422 addr += addr_byte_size;
423 }
424 }
425
Johnny Chen7c1bf922011-02-08 23:49:37 +0000426 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000428 dwarf_reg.num = dwarf_pc;
429 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000430 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000431 if (!success)
432 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000433 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000434 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 addr += addr_byte_size;
437 }
438
439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000440 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000441
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 }
445 return true;
446}
447
Johnny Chen5b442b72011-01-27 19:34:30 +0000448// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000450bool
Johnny Chen9f687722011-02-18 00:02:28 +0000451EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000452{
453#if 0
454 // ARM pseudo code...
455 if (ConditionPassed())
456 {
457 EncodingSpecificOperations();
458 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
459 if d == 15 then
460 ALUWritePC(result); // setflags is always FALSE here
461 else
462 R[d] = result;
463 if setflags then
464 APSR.N = result<31>;
465 APSR.Z = IsZeroBit(result);
466 APSR.C = carry;
467 APSR.V = overflow;
468 }
469#endif
470
471 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000472 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 if (!success)
474 return false;
475
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000478 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481 uint32_t Rd; // the destination register
482 uint32_t imm32;
483 switch (encoding) {
484 case eEncodingT1:
485 Rd = 7;
486 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
487 break;
488 case eEncodingA1:
489 Rd = Bits32(opcode, 15, 12);
490 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
491 break;
492 default:
493 return false;
494 }
495 addr_t sp_offset = imm32;
496 addr_t addr = sp + sp_offset; // a pointer to the stack area
497
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000498 EmulateInstruction::Context context;
499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
500 Register sp_reg;
501 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
502 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000505 return false;
506 }
507 return true;
508}
509
Johnny Chen2ccad832011-01-28 19:57:25 +0000510// Set r7 or ip to the current stack pointer.
511// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000512bool
Johnny Chen9f687722011-02-18 00:02:28 +0000513EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000514{
515#if 0
516 // ARM pseudo code...
517 if (ConditionPassed())
518 {
519 EncodingSpecificOperations();
520 result = R[m];
521 if d == 15 then
522 ALUWritePC(result); // setflags is always FALSE here
523 else
524 R[d] = result;
525 if setflags then
526 APSR.N = result<31>;
527 APSR.Z = IsZeroBit(result);
528 // APSR.C unchanged
529 // APSR.V unchanged
530 }
531#endif
532
533 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000534 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000535 //if (!success)
536 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000537
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000540 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000541 if (!success)
542 return false;
543 uint32_t Rd; // the destination register
544 switch (encoding) {
545 case eEncodingT1:
546 Rd = 7;
547 break;
548 case eEncodingA1:
549 Rd = 12;
550 break;
551 default:
552 return false;
553 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000554
555 EmulateInstruction::Context context;
556 context.type = EmulateInstruction::eContextRegisterPlusOffset;
557 Register sp_reg;
558 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
559 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000560
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000562 return false;
563 }
564 return true;
565}
566
Johnny Chen1c13b622011-01-29 00:11:15 +0000567// Move from high register (r8-r15) to low register (r0-r7).
568// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000569bool
Johnny Chen9f687722011-02-18 00:02:28 +0000570EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000571{
Johnny Chen9f687722011-02-18 00:02:28 +0000572 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000573}
574
575// Move from register to register.
576// MOV (register)
577bool
Johnny Chen9f687722011-02-18 00:02:28 +0000578EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000579{
Johnny Chen1c13b622011-01-29 00:11:15 +0000580#if 0
581 // ARM pseudo code...
582 if (ConditionPassed())
583 {
584 EncodingSpecificOperations();
585 result = R[m];
586 if d == 15 then
587 ALUWritePC(result); // setflags is always FALSE here
588 else
589 R[d] = result;
590 if setflags then
591 APSR.N = result<31>;
592 APSR.Z = IsZeroBit(result);
593 // APSR.C unchanged
594 // APSR.V unchanged
595 }
596#endif
597
598 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000599 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000600 if (!success)
601 return false;
602
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000603 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 {
605 uint32_t Rm; // the source register
606 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000607 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000608 switch (encoding) {
609 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000610 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000611 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000612 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000613 if (Rd == 15 && InITBlock() && !LastInITBlock())
614 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000615 break;
616 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000617 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000620 if (InITBlock())
621 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000622 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 case eEncodingT3:
624 Rd = Bits32(opcode, 11, 8);
625 Rm = Bits32(opcode, 3, 0);
626 setflags = BitIsSet(opcode, 20);
627 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
628 if (setflags && (BadReg(Rd) || BadReg(Rm)))
629 return false;
630 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
631 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
632 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000633 default:
634 return false;
635 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000636 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000637 if (!success)
638 return false;
639
640 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000641 EmulateInstruction::Context context;
642 context.type = EmulateInstruction::eContextRegisterPlusOffset;
643 Register dwarf_reg;
644 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
645 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000646
Johnny Chen10530c22011-02-17 22:37:12 +0000647 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000648 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 }
650 return true;
651}
652
Johnny Chen357c30f2011-02-14 22:04:25 +0000653// Move (immediate) writes an immediate value to the destination register. It
654// can optionally update the condition flags based on the value.
655// MOV (immediate)
656bool
Johnny Chen9f687722011-02-18 00:02:28 +0000657EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000658{
659#if 0
660 // ARM pseudo code...
661 if (ConditionPassed())
662 {
663 EncodingSpecificOperations();
664 result = imm32;
665 if d == 15 then // Can only occur for ARM encoding
666 ALUWritePC(result); // setflags is always FALSE here
667 else
668 R[d] = result;
669 if setflags then
670 APSR.N = result<31>;
671 APSR.Z = IsZeroBit(result);
672 APSR.C = carry;
673 // APSR.V unchanged
674 }
675#endif
676 bool success = false;
677 const uint32_t opcode = OpcodeAsUnsigned (&success);
678 if (!success)
679 return false;
680
681 if (ConditionPassed())
682 {
683 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000684 uint32_t imm32; // the immediate value to be written to Rd
685 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
686 bool setflags;
687 switch (encoding) {
688 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000689 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000690 setflags = !InITBlock();
691 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000692 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000693 break;
694 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000695 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000696 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000697 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000698 if (BadReg(Rd))
699 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000700 break;
701 default:
702 return false;
703 }
704 uint32_t result = imm32;
705
706 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000707 EmulateInstruction::Context context;
708 context.type = EmulateInstruction::eContextImmediate;
709 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000710
Johnny Chen10530c22011-02-17 22:37:12 +0000711 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000712 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000713 }
714 return true;
715}
716
Johnny Chend642a6a2011-02-22 01:01:03 +0000717// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
718// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000719bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000720EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000721{
722#if 0
723 // ARM pseudo code...
724 if (ConditionPassed())
725 {
726 EncodingSpecificOperations();
727 result = NOT(imm32);
728 if d == 15 then // Can only occur for ARM encoding
729 ALUWritePC(result); // setflags is always FALSE here
730 else
731 R[d] = result;
732 if setflags then
733 APSR.N = result<31>;
734 APSR.Z = IsZeroBit(result);
735 APSR.C = carry;
736 // APSR.V unchanged
737 }
738#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000739 bool success = false;
740 const uint32_t opcode = OpcodeAsUnsigned (&success);
741 if (!success)
742 return false;
743
744 if (ConditionPassed())
745 {
746 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000747 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
748 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000749 bool setflags;
750 switch (encoding) {
751 case eEncodingT1:
752 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000753 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000754 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000755 break;
756 case eEncodingA1:
757 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000758 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000759 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
760 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
761 // TODO: Emulate SUBS PC, LR and related instructions.
762 if (Rd == 15 && setflags)
763 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000764 break;
765 default:
766 return false;
767 }
768 uint32_t result = ~imm32;
769
770 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000771 EmulateInstruction::Context context;
772 context.type = EmulateInstruction::eContextImmediate;
773 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000774
Johnny Chen10530c22011-02-17 22:37:12 +0000775 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000776 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000777 }
778 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000779}
780
Johnny Chend642a6a2011-02-22 01:01:03 +0000781// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
782// It can optionally update the condition flags based on the result.
783bool
784EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
785{
786#if 0
787 // ARM pseudo code...
788 if (ConditionPassed())
789 {
790 EncodingSpecificOperations();
791 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
792 result = NOT(shifted);
793 if d == 15 then // Can only occur for ARM encoding
794 ALUWritePC(result); // setflags is always FALSE here
795 else
796 R[d] = result;
797 if setflags then
798 APSR.N = result<31>;
799 APSR.Z = IsZeroBit(result);
800 APSR.C = carry;
801 // APSR.V unchanged
802 }
803#endif
804
805 bool success = false;
806 const uint32_t opcode = OpcodeAsUnsigned (&success);
807 if (!success)
808 return false;
809
810 if (ConditionPassed())
811 {
812 uint32_t Rm; // the source register
813 uint32_t Rd; // the destination register
814 ARM_ShifterType shift_t;
815 uint32_t shift_n; // the shift applied to the value read from Rm
816 bool setflags;
817 uint32_t carry; // the carry bit after the shift operation
818 switch (encoding) {
819 case eEncodingT1:
820 Rd = Bits32(opcode, 2, 0);
821 Rm = Bits32(opcode, 5, 3);
822 setflags = !InITBlock();
823 shift_t = SRType_LSL;
824 shift_n = 0;
825 if (InITBlock())
826 return false;
827 break;
828 case eEncodingT2:
829 Rd = Bits32(opcode, 11, 8);
830 Rm = Bits32(opcode, 3, 0);
831 setflags = BitIsSet(opcode, 20);
832 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
833 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
834 if ((BadReg(Rd) || BadReg(Rm)))
835 return false;
836 case eEncodingA1:
837 Rd = Bits32(opcode, 15, 12);
838 Rm = Bits32(opcode, 3, 0);
839 setflags = BitIsSet(opcode, 20);
840 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
841 break;
842 default:
843 return false;
844 }
845 uint32_t value = ReadCoreReg(Rm, &success);
846 if (!success)
847 return false;
848
849 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
850 uint32_t result = ~shifted;
851
852 // The context specifies that an immediate is to be moved into Rd.
853 EmulateInstruction::Context context;
854 context.type = EmulateInstruction::eContextImmediate;
855 context.SetNoArgs ();
856
857 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
858 return false;
859 }
860 return true;
861}
862
Johnny Chen788e0552011-01-27 22:52:23 +0000863// PC relative immediate load into register, possibly followed by ADD (SP plus register).
864// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000865bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000866EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000867{
868#if 0
869 // ARM pseudo code...
870 if (ConditionPassed())
871 {
872 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
873 base = Align(PC,4);
874 address = if add then (base + imm32) else (base - imm32);
875 data = MemU[address,4];
876 if t == 15 then
877 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
878 elsif UnalignedSupport() || address<1:0> = ‘00’ then
879 R[t] = data;
880 else // Can only apply before ARMv7
881 if CurrentInstrSet() == InstrSet_ARM then
882 R[t] = ROR(data, 8*UInt(address<1:0>));
883 else
884 R[t] = bits(32) UNKNOWN;
885 }
886#endif
887
888 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000889 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000890 if (!success)
891 return false;
892
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000893 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000894 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000895 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000896 if (!success)
897 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000898
899 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000900 EmulateInstruction::Context context;
901 context.type = EmulateInstruction::eContextRegisterPlusOffset;
902 Register pc_reg;
903 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
904 context.SetRegisterPlusOffset (pc_reg, 0);
905
Johnny Chenc9de9102011-02-11 19:12:30 +0000906 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000907 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000908 bool add; // +imm32 or -imm32?
909 addr_t base; // the base address
910 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000911 uint32_t data; // the literal data value from the PC relative load
912 switch (encoding) {
913 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000914 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000915 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000916 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000917 break;
918 case eEncodingT2:
919 Rt = Bits32(opcode, 15, 12);
920 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
921 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000922 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000923 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000924 break;
925 default:
926 return false;
927 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000928
Johnny Chene39f22d2011-02-19 01:36:13 +0000929 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000930 if (add)
931 address = base + imm32;
932 else
933 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000934
935 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000936 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000937 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000938 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000939
940 if (Rt == 15)
941 {
942 if (Bits32(address, 1, 0) == 0)
943 {
944 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000945 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000946 return false;
947 }
948 else
949 return false;
950 }
951 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
952 {
953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
954 return false;
955 }
956 else // We don't handle ARM for now.
957 return false;
958
959 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000960 return false;
961 }
962 return true;
963}
964
Johnny Chen5b442b72011-01-27 19:34:30 +0000965// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000966// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000967bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000968EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000969{
970#if 0
971 // ARM pseudo code...
972 if (ConditionPassed())
973 {
974 EncodingSpecificOperations();
975 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
976 if d == 15 then // Can only occur for ARM encoding
977 ALUWritePC(result); // setflags is always FALSE here
978 else
979 R[d] = result;
980 if setflags then
981 APSR.N = result<31>;
982 APSR.Z = IsZeroBit(result);
983 APSR.C = carry;
984 APSR.V = overflow;
985 }
986#endif
987
988 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000989 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000990 if (!success)
991 return false;
992
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000993 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000994 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000995 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000996 if (!success)
997 return false;
998 uint32_t imm32; // the immediate operand
999 switch (encoding) {
1000 case eEncodingT2:
1001 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1002 break;
1003 default:
1004 return false;
1005 }
1006 addr_t sp_offset = imm32;
1007 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1008
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001009 EmulateInstruction::Context context;
1010 context.type = EmulateInstruction::eContextAdjustStackPointer;
1011 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001012
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001013 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001014 return false;
1015 }
1016 return true;
1017}
1018
1019// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001020// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001021bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001022EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001023{
1024#if 0
1025 // ARM pseudo code...
1026 if (ConditionPassed())
1027 {
1028 EncodingSpecificOperations();
1029 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1030 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1031 if d == 15 then
1032 ALUWritePC(result); // setflags is always FALSE here
1033 else
1034 R[d] = result;
1035 if setflags then
1036 APSR.N = result<31>;
1037 APSR.Z = IsZeroBit(result);
1038 APSR.C = carry;
1039 APSR.V = overflow;
1040 }
1041#endif
1042
1043 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001044 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001045 if (!success)
1046 return false;
1047
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001048 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001049 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001050 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001051 if (!success)
1052 return false;
1053 uint32_t Rm; // the second operand
1054 switch (encoding) {
1055 case eEncodingT2:
1056 Rm = Bits32(opcode, 6, 3);
1057 break;
1058 default:
1059 return false;
1060 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001061 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001062 if (!success)
1063 return false;
1064
1065 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1066
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001067 EmulateInstruction::Context context;
1068 context.type = EmulateInstruction::eContextAdjustStackPointer;
1069 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001070
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001071 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001072 return false;
1073 }
1074 return true;
1075}
1076
Johnny Chen9b8d7832011-02-02 01:13:56 +00001077// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1078// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1079// from Thumb to ARM.
1080// BLX (immediate)
1081bool
1082EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1083{
1084#if 0
1085 // ARM pseudo code...
1086 if (ConditionPassed())
1087 {
1088 EncodingSpecificOperations();
1089 if CurrentInstrSet() == InstrSet_ARM then
1090 LR = PC - 4;
1091 else
1092 LR = PC<31:1> : '1';
1093 if targetInstrSet == InstrSet_ARM then
1094 targetAddress = Align(PC,4) + imm32;
1095 else
1096 targetAddress = PC + imm32;
1097 SelectInstrSet(targetInstrSet);
1098 BranchWritePC(targetAddress);
1099 }
1100#endif
1101
1102 bool success = false;
1103 const uint32_t opcode = OpcodeAsUnsigned (&success);
1104 if (!success)
1105 return false;
1106
1107 if (ConditionPassed())
1108 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001109 EmulateInstruction::Context context;
1110 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001111 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001112 if (!success)
1113 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001114 addr_t lr; // next instruction address
1115 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001116 int32_t imm32; // PC-relative offset
1117 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001118 case eEncodingT1:
1119 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001120 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001121 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001122 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001123 uint32_t J1 = Bit32(opcode, 13);
1124 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001125 uint32_t imm11 = Bits32(opcode, 10, 0);
1126 uint32_t I1 = !(J1 ^ S);
1127 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001128 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001129 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001130 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001131 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001132 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001133 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001134 break;
1135 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001136 case eEncodingT2:
1137 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001138 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001139 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001140 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001141 uint32_t J1 = Bit32(opcode, 13);
1142 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001143 uint32_t imm10L = Bits32(opcode, 10, 1);
1144 uint32_t I1 = !(J1 ^ S);
1145 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001146 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001147 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001148 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001149 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001150 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001151 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001152 break;
1153 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001154 case eEncodingA1:
1155 lr = pc + 4; // return address
1156 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001157 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001158 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001159 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001160 case eEncodingA2:
1161 lr = pc + 4; // return address
1162 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001163 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001164 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001165 break;
1166 default:
1167 return false;
1168 }
1169 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1170 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001171 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001172 return false;
1173 }
1174 return true;
1175}
1176
1177// Branch with Link and Exchange (register) calls a subroutine at an address and
1178// instruction set specified by a register.
1179// BLX (register)
1180bool
1181EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1182{
1183#if 0
1184 // ARM pseudo code...
1185 if (ConditionPassed())
1186 {
1187 EncodingSpecificOperations();
1188 target = R[m];
1189 if CurrentInstrSet() == InstrSet_ARM then
1190 next_instr_addr = PC - 4;
1191 LR = next_instr_addr;
1192 else
1193 next_instr_addr = PC - 2;
1194 LR = next_instr_addr<31:1> : ‘1’;
1195 BXWritePC(target);
1196 }
1197#endif
1198
1199 bool success = false;
1200 const uint32_t opcode = OpcodeAsUnsigned (&success);
1201 if (!success)
1202 return false;
1203
1204 if (ConditionPassed())
1205 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001206 EmulateInstruction::Context context;
1207 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001208 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001209 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001210 if (!success)
1211 return false;
1212 uint32_t Rm; // the register with the target address
1213 switch (encoding) {
1214 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001215 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001216 Rm = Bits32(opcode, 6, 3);
1217 // if m == 15 then UNPREDICTABLE;
1218 if (Rm == 15)
1219 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001220 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001221 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001222 break;
1223 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001224 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001225 Rm = Bits32(opcode, 3, 0);
1226 // if m == 15 then UNPREDICTABLE;
1227 if (Rm == 15)
1228 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001229 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001230 default:
1231 return false;
1232 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001233 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001234 if (!success)
1235 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001236 Register dwarf_reg;
1237 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1238 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001239 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1240 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001241 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001242 return false;
1243 }
1244 return true;
1245}
1246
Johnny Chenab3b3512011-02-12 00:10:51 +00001247// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1248// BX
1249bool
1250EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1251{
1252#if 0
1253 // ARM pseudo code...
1254 if (ConditionPassed())
1255 {
1256 EncodingSpecificOperations();
1257 BXWritePC(R[m]);
1258 }
1259#endif
1260
1261 bool success = false;
1262 const uint32_t opcode = OpcodeAsUnsigned (&success);
1263 if (!success)
1264 return false;
1265
1266 if (ConditionPassed())
1267 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001268 EmulateInstruction::Context context;
1269 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001270 uint32_t Rm; // the register with the target address
1271 switch (encoding) {
1272 case eEncodingT1:
1273 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001274 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001275 return false;
1276 break;
1277 case eEncodingA1:
1278 Rm = Bits32(opcode, 3, 0);
1279 break;
1280 default:
1281 return false;
1282 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001283 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001284 if (!success)
1285 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001286
1287 Register dwarf_reg;
1288 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001289 context.SetRegister (dwarf_reg);
1290 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001291 return false;
1292 }
1293 return true;
1294}
1295
Johnny Chen0d0148e2011-01-28 02:26:08 +00001296// Set r7 to point to some ip offset.
1297// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001298bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001299EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001300{
1301#if 0
1302 // ARM pseudo code...
1303 if (ConditionPassed())
1304 {
1305 EncodingSpecificOperations();
1306 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1307 if d == 15 then // Can only occur for ARM encoding
1308 ALUWritePC(result); // setflags is always FALSE here
1309 else
1310 R[d] = result;
1311 if setflags then
1312 APSR.N = result<31>;
1313 APSR.Z = IsZeroBit(result);
1314 APSR.C = carry;
1315 APSR.V = overflow;
1316 }
1317#endif
1318
1319 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001320 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001321 if (!success)
1322 return false;
1323
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001324 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001325 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001326 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001327 if (!success)
1328 return false;
1329 uint32_t imm32;
1330 switch (encoding) {
1331 case eEncodingA1:
1332 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1333 break;
1334 default:
1335 return false;
1336 }
1337 addr_t ip_offset = imm32;
1338 addr_t addr = ip - ip_offset; // the adjusted ip value
1339
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001340 EmulateInstruction::Context context;
1341 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1342 Register dwarf_reg;
1343 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1344 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001345
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001346 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001347 return false;
1348 }
1349 return true;
1350}
1351
1352// Set ip to point to some stack offset.
1353// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001354bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001355EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001356{
1357#if 0
1358 // ARM pseudo code...
1359 if (ConditionPassed())
1360 {
1361 EncodingSpecificOperations();
1362 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1363 if d == 15 then // Can only occur for ARM encoding
1364 ALUWritePC(result); // setflags is always FALSE here
1365 else
1366 R[d] = result;
1367 if setflags then
1368 APSR.N = result<31>;
1369 APSR.Z = IsZeroBit(result);
1370 APSR.C = carry;
1371 APSR.V = overflow;
1372 }
1373#endif
1374
1375 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001376 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001377 if (!success)
1378 return false;
1379
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001380 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001381 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001382 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001383 if (!success)
1384 return false;
1385 uint32_t imm32;
1386 switch (encoding) {
1387 case eEncodingA1:
1388 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1389 break;
1390 default:
1391 return false;
1392 }
1393 addr_t sp_offset = imm32;
1394 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1395
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001396 EmulateInstruction::Context context;
1397 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1398 Register dwarf_reg;
1399 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1400 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001401
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001402 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001403 return false;
1404 }
1405 return true;
1406}
1407
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001408// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001409bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001410EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001411{
1412#if 0
1413 // ARM pseudo code...
1414 if (ConditionPassed())
1415 {
1416 EncodingSpecificOperations();
1417 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1418 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001419 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001420 else
1421 R[d] = result;
1422 if setflags then
1423 APSR.N = result<31>;
1424 APSR.Z = IsZeroBit(result);
1425 APSR.C = carry;
1426 APSR.V = overflow;
1427 }
1428#endif
1429
1430 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001431 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001432 if (!success)
1433 return false;
1434
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001435 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001436 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001437 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001438 if (!success)
1439 return false;
1440 uint32_t imm32;
1441 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001442 case eEncodingT1:
1443 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001444 case eEncodingT2:
1445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1446 break;
1447 case eEncodingT3:
1448 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1449 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001450 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001451 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001452 break;
1453 default:
1454 return false;
1455 }
1456 addr_t sp_offset = imm32;
1457 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1458
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001459 EmulateInstruction::Context context;
1460 context.type = EmulateInstruction::eContextAdjustStackPointer;
1461 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001462
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001463 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001464 return false;
1465 }
1466 return true;
1467}
1468
Johnny Chen08c25e82011-01-31 18:02:28 +00001469// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001470bool
1471EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001472{
1473#if 0
1474 // ARM pseudo code...
1475 if (ConditionPassed())
1476 {
1477 EncodingSpecificOperations();
1478 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1479 address = if index then offset_addr else R[n];
1480 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1481 if wback then R[n] = offset_addr;
1482 }
1483#endif
1484
1485 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001486 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001487 if (!success)
1488 return false;
1489
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001490 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001491 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001492 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001493 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001494 if (!success)
1495 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001496 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001497 uint32_t imm12;
1498 switch (encoding) {
1499 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001500 Rt = Bits32(opcode, 15, 12);
1501 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001502 break;
1503 default:
1504 return false;
1505 }
1506 addr_t sp_offset = imm12;
1507 addr_t addr = sp - sp_offset;
1508
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001509 EmulateInstruction::Context context;
1510 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1511 Register dwarf_reg;
1512 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001513 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001514 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001515 dwarf_reg.num = dwarf_r0 + Rt;
1516 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001517 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001518 if (!success)
1519 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001520 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001521 return false;
1522 }
1523 else
1524 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001525 dwarf_reg.num = dwarf_pc;
1526 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001527 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001528 if (!success)
1529 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001530 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001531 return false;
1532 }
1533
1534 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001535 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001536
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001537 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001538 return false;
1539 }
1540 return true;
1541}
1542
Johnny Chen08c25e82011-01-31 18:02:28 +00001543// Vector Push stores multiple extension registers to the stack.
1544// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001545bool
1546EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001547{
1548#if 0
1549 // ARM pseudo code...
1550 if (ConditionPassed())
1551 {
1552 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1553 address = SP - imm32;
1554 SP = SP - imm32;
1555 if single_regs then
1556 for r = 0 to regs-1
1557 MemA[address,4] = S[d+r]; address = address+4;
1558 else
1559 for r = 0 to regs-1
1560 // Store as two word-aligned words in the correct order for current endianness.
1561 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1562 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1563 address = address+8;
1564 }
1565#endif
1566
1567 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001568 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001569 if (!success)
1570 return false;
1571
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001572 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001573 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001574 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001575 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001576 if (!success)
1577 return false;
1578 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001579 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001580 uint32_t imm32; // stack offset
1581 uint32_t regs; // number of registers
1582 switch (encoding) {
1583 case eEncodingT1:
1584 case eEncodingA1:
1585 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001586 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001587 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1588 // If UInt(imm8) is odd, see "FSTMX".
1589 regs = Bits32(opcode, 7, 0) / 2;
1590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1591 if (regs == 0 || regs > 16 || (d + regs) > 32)
1592 return false;
1593 break;
1594 case eEncodingT2:
1595 case eEncodingA2:
1596 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001597 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001598 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1599 regs = Bits32(opcode, 7, 0);
1600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1601 if (regs == 0 || regs > 16 || (d + regs) > 32)
1602 return false;
1603 break;
1604 default:
1605 return false;
1606 }
1607 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1608 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1609 addr_t sp_offset = imm32;
1610 addr_t addr = sp - sp_offset;
1611 uint32_t i;
1612
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001613 EmulateInstruction::Context context;
1614 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1615 Register dwarf_reg;
1616 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001617 for (i=d; i<regs; ++i)
1618 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001619 dwarf_reg.num = start_reg + i;
1620 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001621 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001622 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001623 if (!success)
1624 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001625 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001626 return false;
1627 addr += reg_byte_size;
1628 }
1629
1630 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001631 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001632
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001633 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001634 return false;
1635 }
1636 return true;
1637}
1638
Johnny Chen587a0a42011-02-01 18:35:28 +00001639// Vector Pop loads multiple extension registers from the stack.
1640// It also updates SP to point just above the loaded data.
1641bool
1642EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1649 address = SP;
1650 SP = SP + imm32;
1651 if single_regs then
1652 for r = 0 to regs-1
1653 S[d+r] = MemA[address,4]; address = address+4;
1654 else
1655 for r = 0 to regs-1
1656 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1657 // Combine the word-aligned words in the correct order for current endianness.
1658 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1659 }
1660#endif
1661
1662 bool success = false;
1663 const uint32_t opcode = OpcodeAsUnsigned (&success);
1664 if (!success)
1665 return false;
1666
1667 if (ConditionPassed())
1668 {
1669 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001670 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001671 if (!success)
1672 return false;
1673 bool single_regs;
1674 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1675 uint32_t imm32; // stack offset
1676 uint32_t regs; // number of registers
1677 switch (encoding) {
1678 case eEncodingT1:
1679 case eEncodingA1:
1680 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001681 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001682 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1683 // If UInt(imm8) is odd, see "FLDMX".
1684 regs = Bits32(opcode, 7, 0) / 2;
1685 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1686 if (regs == 0 || regs > 16 || (d + regs) > 32)
1687 return false;
1688 break;
1689 case eEncodingT2:
1690 case eEncodingA2:
1691 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001692 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001693 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1694 regs = Bits32(opcode, 7, 0);
1695 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1696 if (regs == 0 || regs > 16 || (d + regs) > 32)
1697 return false;
1698 break;
1699 default:
1700 return false;
1701 }
1702 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1703 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1704 addr_t sp_offset = imm32;
1705 addr_t addr = sp;
1706 uint32_t i;
1707 uint64_t data; // uint64_t to accomodate 64-bit registers.
1708
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001709 EmulateInstruction::Context context;
1710 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1711 Register dwarf_reg;
1712 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001713 for (i=d; i<regs; ++i)
1714 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001715 dwarf_reg.num = start_reg + i;
1716 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001717 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001718 if (!success)
1719 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001720 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001721 return false;
1722 addr += reg_byte_size;
1723 }
1724
1725 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001726 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001727
1728 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1729 return false;
1730 }
1731 return true;
1732}
1733
Johnny Chenb77be412011-02-04 00:40:18 +00001734// SVC (previously SWI)
1735bool
1736EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1737{
1738#if 0
1739 // ARM pseudo code...
1740 if (ConditionPassed())
1741 {
1742 EncodingSpecificOperations();
1743 CallSupervisor();
1744 }
1745#endif
1746
1747 bool success = false;
1748 const uint32_t opcode = OpcodeAsUnsigned (&success);
1749 if (!success)
1750 return false;
1751
1752 if (ConditionPassed())
1753 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001754 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001755 addr_t lr; // next instruction address
1756 if (!success)
1757 return false;
1758 uint32_t imm32; // the immediate constant
1759 uint32_t mode; // ARM or Thumb mode
1760 switch (encoding) {
1761 case eEncodingT1:
1762 lr = (pc + 2) | 1u; // return address
1763 imm32 = Bits32(opcode, 7, 0);
1764 mode = eModeThumb;
1765 break;
1766 case eEncodingA1:
1767 lr = pc + 4; // return address
1768 imm32 = Bits32(opcode, 23, 0);
1769 mode = eModeARM;
1770 break;
1771 default:
1772 return false;
1773 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001774
1775 EmulateInstruction::Context context;
1776 context.type = EmulateInstruction::eContextSupervisorCall;
1777 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001778 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1779 return false;
1780 }
1781 return true;
1782}
1783
Johnny Chenc315f862011-02-05 00:46:10 +00001784// If Then makes up to four following instructions (the IT block) conditional.
1785bool
1786EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1787{
1788#if 0
1789 // ARM pseudo code...
1790 EncodingSpecificOperations();
1791 ITSTATE.IT<7:0> = firstcond:mask;
1792#endif
1793
1794 bool success = false;
1795 const uint32_t opcode = OpcodeAsUnsigned (&success);
1796 if (!success)
1797 return false;
1798
1799 m_it_session.InitIT(Bits32(opcode, 7, 0));
1800 return true;
1801}
1802
Johnny Chen3b620b32011-02-07 20:11:47 +00001803// Branch causes a branch to a target address.
1804bool
1805EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1806{
1807#if 0
1808 // ARM pseudo code...
1809 if (ConditionPassed())
1810 {
1811 EncodingSpecificOperations();
1812 BranchWritePC(PC + imm32);
1813 }
1814#endif
1815
1816 bool success = false;
1817 const uint32_t opcode = OpcodeAsUnsigned (&success);
1818 if (!success)
1819 return false;
1820
Johnny Chen9ee056b2011-02-08 00:06:35 +00001821 if (ConditionPassed())
1822 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001823 EmulateInstruction::Context context;
1824 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001825 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001826 if (!success)
1827 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001828 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001829 int32_t imm32; // PC-relative offset
1830 switch (encoding) {
1831 case eEncodingT1:
1832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1833 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001834 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001835 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001836 break;
1837 case eEncodingT2:
1838 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001839 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001840 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001841 break;
1842 case eEncodingT3:
1843 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1844 {
Johnny Chenbd599902011-02-10 21:39:01 +00001845 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001846 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001847 uint32_t J1 = Bit32(opcode, 13);
1848 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001849 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001850 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001851 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001852 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001853 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001854 break;
1855 }
1856 case eEncodingT4:
1857 {
Johnny Chenbd599902011-02-10 21:39:01 +00001858 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001859 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001860 uint32_t J1 = Bit32(opcode, 13);
1861 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001862 uint32_t imm11 = Bits32(opcode, 10, 0);
1863 uint32_t I1 = !(J1 ^ S);
1864 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001865 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001866 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001867 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001868 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001869 break;
1870 }
1871 case eEncodingA1:
1872 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001873 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001874 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001875 break;
1876 default:
1877 return false;
1878 }
1879 if (!BranchWritePC(context, target))
1880 return false;
1881 }
1882 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001883}
1884
Johnny Chen53ebab72011-02-08 23:21:57 +00001885// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1886// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1887// CBNZ, CBZ
1888bool
1889EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1890{
1891#if 0
1892 // ARM pseudo code...
1893 EncodingSpecificOperations();
1894 if nonzero ^ IsZero(R[n]) then
1895 BranchWritePC(PC + imm32);
1896#endif
1897
1898 bool success = false;
1899 const uint32_t opcode = OpcodeAsUnsigned (&success);
1900 if (!success)
1901 return false;
1902
1903 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00001904 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001905 if (!success)
1906 return false;
1907
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001908 EmulateInstruction::Context context;
1909 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001910 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001911 if (!success)
1912 return false;
1913
1914 addr_t target; // target address
1915 uint32_t imm32; // PC-relative offset to branch forward
1916 bool nonzero;
1917 switch (encoding) {
1918 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001919 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001920 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00001921 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001922 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001923 break;
1924 default:
1925 return false;
1926 }
1927 if (nonzero ^ (reg_val == 0))
1928 if (!BranchWritePC(context, target))
1929 return false;
1930
1931 return true;
1932}
1933
Johnny Chen60299ec2011-02-17 19:34:27 +00001934// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1935// A base register provides a pointer to the table, and a second register supplies an index into the table.
1936// The branch length is twice the value of the byte returned from the table.
1937//
1938// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1939// A base register provides a pointer to the table, and a second register supplies an index into the table.
1940// The branch length is twice the value of the halfword returned from the table.
1941// TBB, TBH
1942bool
1943EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1944{
1945#if 0
1946 // ARM pseudo code...
1947 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1948 if is_tbh then
1949 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1950 else
1951 halfwords = UInt(MemU[R[n]+R[m], 1]);
1952 BranchWritePC(PC + 2*halfwords);
1953#endif
1954
1955 bool success = false;
1956 const uint32_t opcode = OpcodeAsUnsigned (&success);
1957 if (!success)
1958 return false;
1959
1960 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1961 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1962 bool is_tbh; // true if table branch halfword
1963 switch (encoding) {
1964 case eEncodingT1:
1965 Rn = Bits32(opcode, 19, 16);
1966 Rm = Bits32(opcode, 3, 0);
1967 is_tbh = BitIsSet(opcode, 4);
1968 if (Rn == 13 || BadReg(Rm))
1969 return false;
1970 if (InITBlock() && !LastInITBlock())
1971 return false;
1972 break;
1973 default:
1974 return false;
1975 }
1976
1977 // Read the address of the table from the operand register Rn.
1978 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00001979 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001980 if (!success)
1981 return false;
1982
1983 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00001984 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001985 if (!success)
1986 return false;
1987
1988 // the offsetted table address
1989 addr_t addr = base + (is_tbh ? index*2 : index);
1990
1991 // PC-relative offset to branch forward
1992 EmulateInstruction::Context context;
1993 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001994 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001995 if (!success)
1996 return false;
1997
Johnny Chene39f22d2011-02-19 01:36:13 +00001998 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001999 if (!success)
2000 return false;
2001
2002 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002003 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002004 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2005 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2006
2007 if (!BranchWritePC(context, target))
2008 return false;
2009
2010 return true;
2011}
2012
Johnny Chen8fa20592011-02-18 01:22:22 +00002013// This instruction adds an immediate value to a register value, and writes the result to the destination
2014// register. It can optionally update the condition flags based on the result.
2015bool
2016EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2017{
2018#if 0
2019 // ARM pseudo code...
2020 if ConditionPassed() then
2021 EncodingSpecificOperations();
2022 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2023 if d == 15 then
2024 ALUWritePC(result); // setflags is always FALSE here
2025 else
2026 R[d] = result;
2027 if setflags then
2028 APSR.N = result<31>;
2029 APSR.Z = IsZeroBit(result);
2030 APSR.C = carry;
2031 APSR.V = overflow;
2032#endif
2033
2034 bool success = false;
2035 const uint32_t opcode = OpcodeAsUnsigned (&success);
2036 if (!success)
2037 return false;
2038
2039 if (ConditionPassed())
2040 {
2041 uint32_t Rd, Rn;
2042 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2043 bool setflags;
2044 switch (encoding)
2045 {
2046 case eEncodingA1:
2047 Rd = Bits32(opcode, 15, 12);
2048 Rn = Bits32(opcode, 19, 16);
2049 setflags = BitIsSet(opcode, 20);
2050 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2051 break;
2052 default:
2053 return false;
2054 }
2055
Johnny Chen8fa20592011-02-18 01:22:22 +00002056 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002057 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002058 if (!success)
2059 return false;
2060
2061 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2062
2063 EmulateInstruction::Context context;
2064 context.type = EmulateInstruction::eContextImmediate;
2065 context.SetNoArgs ();
2066
2067 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2068 return false;
2069 }
2070 return true;
2071}
2072
Johnny Chend761dcf2011-02-17 22:03:29 +00002073// This instruction adds a register value and an optionally-shifted register value, and writes the result
2074// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002075bool
Johnny Chen9f687722011-02-18 00:02:28 +00002076EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002077{
2078#if 0
2079 // ARM pseudo code...
2080 if ConditionPassed() then
2081 EncodingSpecificOperations();
2082 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2083 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2084 if d == 15 then
2085 ALUWritePC(result); // setflags is always FALSE here
2086 else
2087 R[d] = result;
2088 if setflags then
2089 APSR.N = result<31>;
2090 APSR.Z = IsZeroBit(result);
2091 APSR.C = carry;
2092 APSR.V = overflow;
2093#endif
2094
2095 bool success = false;
2096 const uint32_t opcode = OpcodeAsUnsigned (&success);
2097 if (!success)
2098 return false;
2099
2100 if (ConditionPassed())
2101 {
2102 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002103 ARM_ShifterType shift_t;
2104 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002105 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002106 switch (encoding)
2107 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002108 case eEncodingT1:
2109 Rd = Bits32(opcode, 2, 0);
2110 Rn = Bits32(opcode, 5, 3);
2111 Rm = Bits32(opcode, 8, 6);
2112 setflags = !InITBlock();
2113 shift_t = SRType_LSL;
2114 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002115 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002116 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002117 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002118 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002119 shift_t = SRType_LSL;
2120 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002121 if (Rn == 15 && Rm == 15)
2122 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002123 if (Rd == 15 && InITBlock() && !LastInITBlock())
2124 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002125 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002126 case eEncodingA1:
2127 Rd = Bits32(opcode, 15, 12);
2128 Rn = Bits32(opcode, 19, 16);
2129 Rm = Bits32(opcode, 3, 0);
2130 setflags = BitIsSet(opcode, 20);
2131 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2132 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002133 default:
2134 return false;
2135 }
2136
Johnny Chen26863dc2011-02-09 23:43:29 +00002137 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002138 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002139 if (!success)
2140 return false;
2141
2142 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002143 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002144 if (!success)
2145 return false;
2146
Johnny Chene97c0d52011-02-18 19:32:20 +00002147 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002148 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002149
2150 EmulateInstruction::Context context;
2151 context.type = EmulateInstruction::eContextImmediate;
2152 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002153
Johnny Chen10530c22011-02-17 22:37:12 +00002154 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002155 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002156 }
2157 return true;
2158}
2159
Johnny Chen34075cb2011-02-22 01:56:31 +00002160// Compare Negative (immediate) adds a register value and an immediate value.
2161// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002162bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002163EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2164{
2165#if 0
2166 // ARM pseudo code...
2167 if ConditionPassed() then
2168 EncodingSpecificOperations();
2169 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2170 APSR.N = result<31>;
2171 APSR.Z = IsZeroBit(result);
2172 APSR.C = carry;
2173 APSR.V = overflow;
2174#endif
2175
2176 bool success = false;
2177 const uint32_t opcode = OpcodeAsUnsigned (&success);
2178 if (!success)
2179 return false;
2180
2181 uint32_t Rn; // the first operand
2182 uint32_t imm32; // the immediate value to be compared with
2183 switch (encoding) {
2184 case eEncodingT1:
2185 Rn = Bits32(opcode, 10, 8);
2186 imm32 = Bits32(opcode, 7, 0);
2187 case eEncodingA1:
2188 Rn = Bits32(opcode, 19, 16);
2189 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2190 break;
2191 default:
2192 return false;
2193 }
2194 // Read the register value from the operand register Rn.
2195 uint32_t reg_val = ReadCoreReg(Rn, &success);
2196 if (!success)
2197 return false;
2198
2199 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2200
2201 EmulateInstruction::Context context;
2202 context.type = EmulateInstruction::eContextImmediate;
2203 context.SetNoArgs ();
2204 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2205 return false;
2206
2207 return true;
2208}
2209
2210// Compare Negative (register) adds a register value and an optionally-shifted register value.
2211// It updates the condition flags based on the result, and discards the result.
2212bool
2213EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2214{
2215#if 0
2216 // ARM pseudo code...
2217 if ConditionPassed() then
2218 EncodingSpecificOperations();
2219 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2220 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2221 APSR.N = result<31>;
2222 APSR.Z = IsZeroBit(result);
2223 APSR.C = carry;
2224 APSR.V = overflow;
2225#endif
2226
2227 bool success = false;
2228 const uint32_t opcode = OpcodeAsUnsigned (&success);
2229 if (!success)
2230 return false;
2231
2232 uint32_t Rn; // the first operand
2233 uint32_t Rm; // the second operand
2234 ARM_ShifterType shift_t;
2235 uint32_t shift_n; // the shift applied to the value read from Rm
2236 switch (encoding) {
2237 case eEncodingT1:
2238 Rn = Bits32(opcode, 2, 0);
2239 Rm = Bits32(opcode, 5, 3);
2240 shift_t = SRType_LSL;
2241 shift_n = 0;
2242 break;
2243 case eEncodingT2:
2244 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2245 Rm = Bits32(opcode, 6, 3);
2246 shift_t = SRType_LSL;
2247 shift_n = 0;
2248 if (Rn < 8 && Rm < 8)
2249 return false;
2250 if (Rn == 15 || Rm == 15)
2251 return false;
2252 break;
2253 case eEncodingA1:
2254 Rn = Bits32(opcode, 19, 16);
2255 Rm = Bits32(opcode, 3, 0);
2256 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2257 default:
2258 return false;
2259 }
2260 // Read the register value from register Rn.
2261 uint32_t val1 = ReadCoreReg(Rn, &success);
2262 if (!success)
2263 return false;
2264
2265 // Read the register value from register Rm.
2266 uint32_t val2 = ReadCoreReg(Rm, &success);
2267 if (!success)
2268 return false;
2269
2270 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2271 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
2272
2273 EmulateInstruction::Context context;
2274 context.type = EmulateInstruction::eContextImmediate;
2275 context.SetNoArgs();
2276 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2277 return false;
2278
2279 return true;
2280}
2281
2282// Compare (immediate) subtracts an immediate value from a register value.
2283// It updates the condition flags based on the result, and discards the result.
2284bool
2285EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002286{
2287#if 0
2288 // ARM pseudo code...
2289 if ConditionPassed() then
2290 EncodingSpecificOperations();
2291 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2292 APSR.N = result<31>;
2293 APSR.Z = IsZeroBit(result);
2294 APSR.C = carry;
2295 APSR.V = overflow;
2296#endif
2297
2298 bool success = false;
2299 const uint32_t opcode = OpcodeAsUnsigned (&success);
2300 if (!success)
2301 return false;
2302
2303 uint32_t Rn; // the first operand
2304 uint32_t imm32; // the immediate value to be compared with
2305 switch (encoding) {
2306 case eEncodingT1:
2307 Rn = Bits32(opcode, 10, 8);
2308 imm32 = Bits32(opcode, 7, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002309 case eEncodingA1:
2310 Rn = Bits32(opcode, 19, 16);
2311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002312 break;
2313 default:
2314 return false;
2315 }
2316 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002317 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002318 if (!success)
2319 return false;
2320
Johnny Chen10530c22011-02-17 22:37:12 +00002321 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2322
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002323 EmulateInstruction::Context context;
2324 context.type = EmulateInstruction::eContextImmediate;
2325 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002326 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2327 return false;
2328
Johnny Chend4dc4442011-02-11 02:02:56 +00002329 return true;
2330}
2331
Johnny Chen34075cb2011-02-22 01:56:31 +00002332// Compare (register) subtracts an optionally-shifted register value from a register value.
2333// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002334bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002335EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002336{
2337#if 0
2338 // ARM pseudo code...
2339 if ConditionPassed() then
2340 EncodingSpecificOperations();
2341 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2342 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2343 APSR.N = result<31>;
2344 APSR.Z = IsZeroBit(result);
2345 APSR.C = carry;
2346 APSR.V = overflow;
2347#endif
2348
2349 bool success = false;
2350 const uint32_t opcode = OpcodeAsUnsigned (&success);
2351 if (!success)
2352 return false;
2353
2354 uint32_t Rn; // the first operand
2355 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002356 ARM_ShifterType shift_t;
2357 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002358 switch (encoding) {
2359 case eEncodingT1:
2360 Rn = Bits32(opcode, 2, 0);
2361 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002362 shift_t = SRType_LSL;
2363 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002364 break;
2365 case eEncodingT2:
2366 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2367 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002368 shift_t = SRType_LSL;
2369 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002370 if (Rn < 8 && Rm < 8)
2371 return false;
2372 if (Rn == 15 || Rm == 15)
2373 return false;
2374 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002375 case eEncodingA1:
2376 Rn = Bits32(opcode, 19, 16);
2377 Rm = Bits32(opcode, 3, 0);
2378 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
Johnny Chene4a4d302011-02-11 21:53:58 +00002379 default:
2380 return false;
2381 }
2382 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002383 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002384 if (!success)
2385 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002386
Johnny Chene4a4d302011-02-11 21:53:58 +00002387 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002388 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002389 if (!success)
2390 return false;
2391
Johnny Chen34075cb2011-02-22 01:56:31 +00002392 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2393 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002394
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002395 EmulateInstruction::Context context;
2396 context.type = EmulateInstruction::eContextImmediate;
2397 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002398 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2399 return false;
2400
Johnny Chene4a4d302011-02-11 21:53:58 +00002401 return true;
2402}
2403
Johnny Chen82f16aa2011-02-15 20:10:55 +00002404// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2405// shifting in copies of its sign bit, and writes the result to the destination register. It can
2406// optionally update the condition flags based on the result.
2407bool
2408EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2409{
2410#if 0
2411 // ARM pseudo code...
2412 if ConditionPassed() then
2413 EncodingSpecificOperations();
2414 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2415 if d == 15 then // Can only occur for ARM encoding
2416 ALUWritePC(result); // setflags is always FALSE here
2417 else
2418 R[d] = result;
2419 if setflags then
2420 APSR.N = result<31>;
2421 APSR.Z = IsZeroBit(result);
2422 APSR.C = carry;
2423 // APSR.V unchanged
2424#endif
2425
Johnny Chen41a0a152011-02-16 01:27:54 +00002426 return EmulateShiftImm(encoding, SRType_ASR);
2427}
2428
2429// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2430// shifting in copies of its sign bit, and writes the result to the destination register.
2431// The variable number of bits is read from the bottom byte of a register. It can optionally update
2432// the condition flags based on the result.
2433bool
2434EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2435{
2436#if 0
2437 // ARM pseudo code...
2438 if ConditionPassed() then
2439 EncodingSpecificOperations();
2440 shift_n = UInt(R[m]<7:0>);
2441 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2442 R[d] = result;
2443 if setflags then
2444 APSR.N = result<31>;
2445 APSR.Z = IsZeroBit(result);
2446 APSR.C = carry;
2447 // APSR.V unchanged
2448#endif
2449
2450 return EmulateShiftReg(encoding, SRType_ASR);
2451}
2452
2453// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2454// shifting in zeros, and writes the result to the destination register. It can optionally
2455// update the condition flags based on the result.
2456bool
2457EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2458{
2459#if 0
2460 // ARM pseudo code...
2461 if ConditionPassed() then
2462 EncodingSpecificOperations();
2463 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2464 if d == 15 then // Can only occur for ARM encoding
2465 ALUWritePC(result); // setflags is always FALSE here
2466 else
2467 R[d] = result;
2468 if setflags then
2469 APSR.N = result<31>;
2470 APSR.Z = IsZeroBit(result);
2471 APSR.C = carry;
2472 // APSR.V unchanged
2473#endif
2474
2475 return EmulateShiftImm(encoding, SRType_LSL);
2476}
2477
2478// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2479// shifting in zeros, and writes the result to the destination register. The variable number
2480// of bits is read from the bottom byte of a register. It can optionally update the condition
2481// flags based on the result.
2482bool
2483EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2484{
2485#if 0
2486 // ARM pseudo code...
2487 if ConditionPassed() then
2488 EncodingSpecificOperations();
2489 shift_n = UInt(R[m]<7:0>);
2490 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2491 R[d] = result;
2492 if setflags then
2493 APSR.N = result<31>;
2494 APSR.Z = IsZeroBit(result);
2495 APSR.C = carry;
2496 // APSR.V unchanged
2497#endif
2498
2499 return EmulateShiftReg(encoding, SRType_LSL);
2500}
2501
2502// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2503// shifting in zeros, and writes the result to the destination register. It can optionally
2504// update the condition flags based on the result.
2505bool
2506EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2507{
2508#if 0
2509 // ARM pseudo code...
2510 if ConditionPassed() then
2511 EncodingSpecificOperations();
2512 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2513 if d == 15 then // Can only occur for ARM encoding
2514 ALUWritePC(result); // setflags is always FALSE here
2515 else
2516 R[d] = result;
2517 if setflags then
2518 APSR.N = result<31>;
2519 APSR.Z = IsZeroBit(result);
2520 APSR.C = carry;
2521 // APSR.V unchanged
2522#endif
2523
2524 return EmulateShiftImm(encoding, SRType_LSR);
2525}
2526
2527// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2528// shifting in zeros, and writes the result to the destination register. The variable number
2529// of bits is read from the bottom byte of a register. It can optionally update the condition
2530// flags based on the result.
2531bool
2532EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2533{
2534#if 0
2535 // ARM pseudo code...
2536 if ConditionPassed() then
2537 EncodingSpecificOperations();
2538 shift_n = UInt(R[m]<7:0>);
2539 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2540 R[d] = result;
2541 if setflags then
2542 APSR.N = result<31>;
2543 APSR.Z = IsZeroBit(result);
2544 APSR.C = carry;
2545 // APSR.V unchanged
2546#endif
2547
2548 return EmulateShiftReg(encoding, SRType_LSR);
2549}
2550
Johnny Cheneeab4852011-02-16 22:14:44 +00002551// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2552// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2553// It can optionally update the condition flags based on the result.
2554bool
2555EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2556{
2557#if 0
2558 // ARM pseudo code...
2559 if ConditionPassed() then
2560 EncodingSpecificOperations();
2561 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2562 if d == 15 then // Can only occur for ARM encoding
2563 ALUWritePC(result); // setflags is always FALSE here
2564 else
2565 R[d] = result;
2566 if setflags then
2567 APSR.N = result<31>;
2568 APSR.Z = IsZeroBit(result);
2569 APSR.C = carry;
2570 // APSR.V unchanged
2571#endif
2572
2573 return EmulateShiftImm(encoding, SRType_ROR);
2574}
2575
2576// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2577// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2578// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2579// flags based on the result.
2580bool
2581EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2582{
2583#if 0
2584 // ARM pseudo code...
2585 if ConditionPassed() then
2586 EncodingSpecificOperations();
2587 shift_n = UInt(R[m]<7:0>);
2588 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2589 R[d] = result;
2590 if setflags then
2591 APSR.N = result<31>;
2592 APSR.Z = IsZeroBit(result);
2593 APSR.C = carry;
2594 // APSR.V unchanged
2595#endif
2596
2597 return EmulateShiftReg(encoding, SRType_ROR);
2598}
2599
2600// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2601// with the carry flag shifted into bit [31].
2602//
2603// RRX can optionally update the condition flags based on the result.
2604// In that case, bit [0] is shifted into the carry flag.
2605bool
2606EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2607{
2608#if 0
2609 // ARM pseudo code...
2610 if ConditionPassed() then
2611 EncodingSpecificOperations();
2612 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2613 if d == 15 then // Can only occur for ARM encoding
2614 ALUWritePC(result); // setflags is always FALSE here
2615 else
2616 R[d] = result;
2617 if setflags then
2618 APSR.N = result<31>;
2619 APSR.Z = IsZeroBit(result);
2620 APSR.C = carry;
2621 // APSR.V unchanged
2622#endif
2623
2624 return EmulateShiftImm(encoding, SRType_RRX);
2625}
2626
Johnny Chen41a0a152011-02-16 01:27:54 +00002627bool
2628EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2629{
2630 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2631
Johnny Chen82f16aa2011-02-15 20:10:55 +00002632 bool success = false;
2633 const uint32_t opcode = OpcodeAsUnsigned (&success);
2634 if (!success)
2635 return false;
2636
2637 if (ConditionPassed())
2638 {
Johnny Chene7f89532011-02-15 23:22:46 +00002639 uint32_t Rd; // the destination register
2640 uint32_t Rm; // the first operand register
2641 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002642 uint32_t carry; // the carry bit after the shift operation
2643 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002644
2645 // Special case handling!
2646 // A8.6.139 ROR (immediate) -- Encoding T1
2647 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2648 {
2649 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2650 // have the same decoding of bit fields as the other Thumb2 shift operations.
2651 encoding = eEncodingT2;
2652 }
2653
Johnny Chen82f16aa2011-02-15 20:10:55 +00002654 switch (encoding) {
2655 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002656 // Due to the above special case handling!
2657 assert(shift_type != SRType_ROR);
2658
Johnny Chen82f16aa2011-02-15 20:10:55 +00002659 Rd = Bits32(opcode, 2, 0);
2660 Rm = Bits32(opcode, 5, 3);
2661 setflags = !InITBlock();
2662 imm5 = Bits32(opcode, 10, 6);
2663 break;
2664 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002665 // A8.6.141 RRX
2666 assert(shift_type != SRType_RRX);
2667
Johnny Chen82f16aa2011-02-15 20:10:55 +00002668 Rd = Bits32(opcode, 11, 8);
2669 Rm = Bits32(opcode, 3, 0);
2670 setflags = BitIsSet(opcode, 20);
2671 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2672 if (BadReg(Rd) || BadReg(Rm))
2673 return false;
2674 break;
2675 case eEncodingA1:
2676 Rd = Bits32(opcode, 15, 12);
2677 Rm = Bits32(opcode, 3, 0);
2678 setflags = BitIsSet(opcode, 20);
2679 imm5 = Bits32(opcode, 11, 7);
2680 break;
2681 default:
2682 return false;
2683 }
2684
Johnny Cheneeab4852011-02-16 22:14:44 +00002685 // A8.6.139 ROR (immediate)
2686 if (shift_type == SRType_ROR && imm5 == 0)
2687 shift_type = SRType_RRX;
2688
Johnny Chen82f16aa2011-02-15 20:10:55 +00002689 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002690 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002691 if (!success)
2692 return false;
2693
Johnny Cheneeab4852011-02-16 22:14:44 +00002694 // Decode the shift amount if not RRX.
2695 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002696
Johnny Chene97c0d52011-02-18 19:32:20 +00002697 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002698
2699 // The context specifies that an immediate is to be moved into Rd.
2700 EmulateInstruction::Context context;
2701 context.type = EmulateInstruction::eContextImmediate;
2702 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002703
Johnny Chen10530c22011-02-17 22:37:12 +00002704 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002705 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002706 }
2707 return true;
2708}
2709
Johnny Chene7f89532011-02-15 23:22:46 +00002710bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002711EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002712{
Johnny Chen41a0a152011-02-16 01:27:54 +00002713 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002714
2715 bool success = false;
2716 const uint32_t opcode = OpcodeAsUnsigned (&success);
2717 if (!success)
2718 return false;
2719
2720 if (ConditionPassed())
2721 {
2722 uint32_t Rd; // the destination register
2723 uint32_t Rn; // the first operand register
2724 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2725 uint32_t carry; // the carry bit after the shift operation
2726 bool setflags;
2727 switch (encoding) {
2728 case eEncodingT1:
2729 Rd = Bits32(opcode, 2, 0);
2730 Rn = Rd;
2731 Rm = Bits32(opcode, 5, 3);
2732 setflags = !InITBlock();
2733 break;
2734 case eEncodingT2:
2735 Rd = Bits32(opcode, 11, 8);
2736 Rn = Bits32(opcode, 19, 16);
2737 Rm = Bits32(opcode, 3, 0);
2738 setflags = BitIsSet(opcode, 20);
2739 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2740 return false;
2741 break;
2742 case eEncodingA1:
2743 Rd = Bits32(opcode, 15, 12);
2744 Rn = Bits32(opcode, 3, 0);
2745 Rm = Bits32(opcode, 11, 8);
2746 setflags = BitIsSet(opcode, 20);
2747 if (Rd == 15 || Rn == 15 || Rm == 15)
2748 return false;
2749 break;
2750 default:
2751 return false;
2752 }
2753
2754 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002755 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002756 if (!success)
2757 return false;
2758 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002759 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002760 if (!success)
2761 return false;
2762
2763 // Get the shift amount.
2764 uint32_t amt = Bits32(val, 7, 0);
2765
Johnny Chene97c0d52011-02-18 19:32:20 +00002766 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002767
2768 // The context specifies that an immediate is to be moved into Rd.
2769 EmulateInstruction::Context context;
2770 context.type = EmulateInstruction::eContextImmediate;
2771 context.SetNoArgs ();
2772
Johnny Chen10530c22011-02-17 22:37:12 +00002773 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002774 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002775 }
2776 return true;
2777}
2778
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002779// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002780// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002781// can be written back to the base register.
2782bool
2783EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2784{
2785#if 0
2786 // ARM pseudo code...
2787 if ConditionPassed()
2788 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2789 address = R[n];
2790
2791 for i = 0 to 14
2792 if registers<i> == '1' then
2793 R[i] = MemA[address, 4]; address = address + 4;
2794 if registers<15> == '1' then
2795 LoadWritePC (MemA[address, 4]);
2796
2797 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2798 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2799
2800#endif
2801
2802 bool success = false;
2803 const uint32_t opcode = OpcodeAsUnsigned (&success);
2804 if (!success)
2805 return false;
2806
2807 if (ConditionPassed())
2808 {
2809 uint32_t n;
2810 uint32_t registers = 0;
2811 bool wback;
2812 const uint32_t addr_byte_size = GetAddressByteSize();
2813 switch (encoding)
2814 {
2815 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002816 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002817 n = Bits32 (opcode, 10, 8);
2818 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002819 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002820 wback = BitIsClear (registers, n);
2821 // if BitCount(registers) < 1 then UNPREDICTABLE;
2822 if (BitCount(registers) < 1)
2823 return false;
2824 break;
2825 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002826 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2827 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002828 n = Bits32 (opcode, 19, 16);
2829 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002830 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002831 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002832
2833 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002834 if ((n == 15)
2835 || (BitCount (registers) < 2)
2836 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2837 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002838
2839 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002840 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002841 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002842
2843 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002844 if (wback
2845 && BitIsSet (registers, n))
2846 return false;
2847 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002848
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002849 case eEncodingA1:
2850 n = Bits32 (opcode, 19, 16);
2851 registers = Bits32 (opcode, 15, 0);
2852 wback = BitIsSet (opcode, 21);
2853 if ((n == 15)
2854 || (BitCount (registers) < 1))
2855 return false;
2856 break;
2857 default:
2858 return false;
2859 }
2860
2861 int32_t offset = 0;
2862 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2863 if (!success)
2864 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002865
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002866 EmulateInstruction::Context context;
2867 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2868 Register dwarf_reg;
2869 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2870 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002871
2872 for (int i = 0; i < 14; ++i)
2873 {
2874 if (BitIsSet (registers, i))
2875 {
Caroline Tice85aab332011-02-08 23:56:10 +00002876 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002877 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002878 if (wback && (n == 13)) // Pop Instruction
2879 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2880
2881 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002882 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002883 if (!success)
2884 return false;
2885
2886 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2887 return false;
2888
2889 offset += addr_byte_size;
2890 }
2891 }
2892
2893 if (BitIsSet (registers, 15))
2894 {
2895 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002896 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002897 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002898 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002899 if (!success)
2900 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002901 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002902 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002903 return false;
2904 }
2905
2906 if (wback && BitIsClear (registers, n))
2907 {
Caroline Ticefa172202011-02-11 22:49:54 +00002908 // R[n] = R[n] + 4 * BitCount (registers)
2909 int32_t offset = addr_byte_size * BitCount (registers);
2910 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002911 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002912
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002913 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2914 return false;
2915 }
2916 if (wback && BitIsSet (registers, n))
2917 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002918 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002919 }
2920 return true;
2921}
Caroline Tice713c2662011-02-11 17:59:55 +00002922
2923// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2924// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2925// can optionally be written back tot he base registers.
2926bool
2927EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2928{
2929#if 0
2930 // ARM pseudo code...
2931 if ConditionPassed() then
2932 EncodingSpecificOperations();
2933 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002934
Caroline Tice713c2662011-02-11 17:59:55 +00002935 for i = 0 to 14
2936 if registers<i> == ’1’ then
2937 R[i] = MemA[address,4]; address = address + 4;
2938
2939 if registers<15> == ’1’ then
2940 LoadWritePC(MemA[address,4]);
2941
2942 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2943 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2944#endif
2945
2946 bool success = false;
2947 const uint32_t opcode = OpcodeAsUnsigned (&success);
2948 if (!success)
2949 return false;
2950
2951 if (ConditionPassed())
2952 {
2953 uint32_t n;
2954 uint32_t registers = 0;
2955 bool wback;
2956 const uint32_t addr_byte_size = GetAddressByteSize();
2957
2958 // EncodingSpecificOperations();
2959 switch (encoding)
2960 {
2961 case eEncodingA1:
2962 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2963 n = Bits32 (opcode, 19, 16);
2964 registers = Bits32 (opcode, 15, 0);
2965 wback = BitIsSet (opcode, 21);
2966
2967 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2968 if ((n == 15) || (BitCount (registers) < 1))
2969 return false;
2970
2971 break;
2972
2973 default:
2974 return false;
2975 }
2976 // address = R[n] - 4*BitCount(registers) + 4;
2977
2978 int32_t offset = 0;
2979 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2980
2981 if (!success)
2982 return false;
2983
2984 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2985
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002986 EmulateInstruction::Context context;
2987 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2988 Register dwarf_reg;
2989 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2990 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002991
2992 // for i = 0 to 14
2993 for (int i = 0; i < 14; ++i)
2994 {
2995 // if registers<i> == ’1’ then
2996 if (BitIsSet (registers, i))
2997 {
2998 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002999 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003000 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003001 if (!success)
3002 return false;
3003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3004 return false;
3005 offset += addr_byte_size;
3006 }
3007 }
3008
3009 // if registers<15> == ’1’ then
3010 // LoadWritePC(MemA[address,4]);
3011 if (BitIsSet (registers, 15))
3012 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003013 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003014 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003015 if (!success)
3016 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003017 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003018 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003019 return false;
3020 }
3021
3022 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3023 if (wback && BitIsClear (registers, n))
3024 {
Caroline Tice713c2662011-02-11 17:59:55 +00003025 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3026 if (!success)
3027 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003028
3029 offset = (addr_byte_size * BitCount (registers)) * -1;
3030 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003031 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003032 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003033 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3034 return false;
3035 }
3036
3037 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3038 if (wback && BitIsSet (registers, n))
3039 return WriteBits32Unknown (n);
3040 }
3041 return true;
3042}
3043
3044// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3045// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3046// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003047bool
3048EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3049{
3050#if 0
3051 // ARM pseudo code...
3052 if ConditionPassed() then
3053 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3054 address = R[n] - 4*BitCount(registers);
3055
3056 for i = 0 to 14
3057 if registers<i> == ’1’ then
3058 R[i] = MemA[address,4]; address = address + 4;
3059 if registers<15> == ’1’ then
3060 LoadWritePC(MemA[address,4]);
3061
3062 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3063 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3064#endif
3065
3066 bool success = false;
3067 const uint32_t opcode = OpcodeAsUnsigned (&success);
3068 if (!success)
3069 return false;
3070
3071 if (ConditionPassed())
3072 {
3073 uint32_t n;
3074 uint32_t registers = 0;
3075 bool wback;
3076 const uint32_t addr_byte_size = GetAddressByteSize();
3077 switch (encoding)
3078 {
3079 case eEncodingT1:
3080 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3081 n = Bits32 (opcode, 19, 16);
3082 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003083 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003084 wback = BitIsSet (opcode, 21);
3085
3086 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3087 if ((n == 15)
3088 || (BitCount (registers) < 2)
3089 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3090 return false;
3091
3092 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003093 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003094 return false;
3095
3096 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3097 if (wback && BitIsSet (registers, n))
3098 return false;
3099
3100 break;
3101
3102 case eEncodingA1:
3103 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3104 n = Bits32 (opcode, 19, 16);
3105 registers = Bits32 (opcode, 15, 0);
3106 wback = BitIsSet (opcode, 21);
3107
3108 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3109 if ((n == 15) || (BitCount (registers) < 1))
3110 return false;
3111
3112 break;
3113
3114 default:
3115 return false;
3116 }
3117
Caroline Tice713c2662011-02-11 17:59:55 +00003118 // address = R[n] - 4*BitCount(registers);
3119
Caroline Tice0b29e242011-02-08 23:16:02 +00003120 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003121 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3122
3123 if (!success)
3124 return false;
3125
3126 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003127 EmulateInstruction::Context context;
3128 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3129 Register dwarf_reg;
3130 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3131 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003132
3133 for (int i = 0; i < 14; ++i)
3134 {
3135 if (BitIsSet (registers, i))
3136 {
3137 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003138 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003139 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003140 if (!success)
3141 return false;
3142
3143 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3144 return false;
3145
3146 offset += addr_byte_size;
3147 }
3148 }
3149
3150 // if registers<15> == ’1’ then
3151 // LoadWritePC(MemA[address,4]);
3152 if (BitIsSet (registers, 15))
3153 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003154 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003155 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003156 if (!success)
3157 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003158 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003159 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003160 return false;
3161 }
3162
3163 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3164 if (wback && BitIsClear (registers, n))
3165 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003166 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3167 if (!success)
3168 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003169
3170 offset = (addr_byte_size * BitCount (registers)) * -1;
3171 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003172 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003173 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003174 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3175 return false;
3176 }
3177
3178 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3179 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003180 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003181 }
3182 return true;
3183}
Caroline Tice85aab332011-02-08 23:56:10 +00003184
Caroline Tice713c2662011-02-11 17:59:55 +00003185// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3186// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3187// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003188bool
3189EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3190{
3191#if 0
3192 if ConditionPassed() then
3193 EncodingSpecificOperations();
3194 address = R[n] + 4;
3195
3196 for i = 0 to 14
3197 if registers<i> == ’1’ then
3198 R[i] = MemA[address,4]; address = address + 4;
3199 if registers<15> == ’1’ then
3200 LoadWritePC(MemA[address,4]);
3201
3202 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3203 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3204#endif
3205
3206 bool success = false;
3207 const uint32_t opcode = OpcodeAsUnsigned (&success);
3208 if (!success)
3209 return false;
3210
3211 if (ConditionPassed())
3212 {
3213 uint32_t n;
3214 uint32_t registers = 0;
3215 bool wback;
3216 const uint32_t addr_byte_size = GetAddressByteSize();
3217 switch (encoding)
3218 {
3219 case eEncodingA1:
3220 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3221 n = Bits32 (opcode, 19, 16);
3222 registers = Bits32 (opcode, 15, 0);
3223 wback = BitIsSet (opcode, 21);
3224
3225 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3226 if ((n == 15) || (BitCount (registers) < 1))
3227 return false;
3228
3229 break;
3230 default:
3231 return false;
3232 }
3233 // address = R[n] + 4;
3234
3235 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003236 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3237
3238 if (!success)
3239 return false;
3240
3241 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003242
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003243 EmulateInstruction::Context context;
3244 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3245 Register dwarf_reg;
3246 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3247 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003248
3249 for (int i = 0; i < 14; ++i)
3250 {
3251 if (BitIsSet (registers, i))
3252 {
3253 // R[i] = MemA[address,4]; address = address + 4;
3254
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003255 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003256 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003257 if (!success)
3258 return false;
3259
3260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3261 return false;
3262
3263 offset += addr_byte_size;
3264 }
3265 }
3266
3267 // if registers<15> == ’1’ then
3268 // LoadWritePC(MemA[address,4]);
3269 if (BitIsSet (registers, 15))
3270 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003271 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003272 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003273 if (!success)
3274 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003275 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003276 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003277 return false;
3278 }
3279
3280 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3281 if (wback && BitIsClear (registers, n))
3282 {
Caroline Tice85aab332011-02-08 23:56:10 +00003283 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3284 if (!success)
3285 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003286
3287 offset = addr_byte_size * BitCount (registers);
3288 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003289 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003290 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3292 return false;
3293 }
3294
3295 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3296 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003297 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003298 }
3299 return true;
3300}
Caroline Tice0b29e242011-02-08 23:16:02 +00003301
Johnny Chenef21b592011-02-10 01:52:38 +00003302// Load Register (immediate) calculates an address from a base register value and
3303// an immediate offset, loads a word from memory, and writes to a register.
3304// LDR (immediate, Thumb)
3305bool
3306EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3307{
3308#if 0
3309 // ARM pseudo code...
3310 if (ConditionPassed())
3311 {
3312 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3313 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3314 address = if index then offset_addr else R[n];
3315 data = MemU[address,4];
3316 if wback then R[n] = offset_addr;
3317 if t == 15 then
3318 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3319 elsif UnalignedSupport() || address<1:0> = '00' then
3320 R[t] = data;
3321 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3322 }
3323#endif
3324
3325 bool success = false;
3326 const uint32_t opcode = OpcodeAsUnsigned (&success);
3327 if (!success)
3328 return false;
3329
3330 if (ConditionPassed())
3331 {
3332 uint32_t Rt; // the destination register
3333 uint32_t Rn; // the base register
3334 uint32_t imm32; // the immediate offset used to form the address
3335 addr_t offset_addr; // the offset address
3336 addr_t address; // the calculated address
3337 uint32_t data; // the literal data value from memory load
3338 bool add, index, wback;
3339 switch (encoding) {
3340 case eEncodingT1:
3341 Rt = Bits32(opcode, 5, 3);
3342 Rn = Bits32(opcode, 2, 0);
3343 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3344 // index = TRUE; add = TRUE; wback = FALSE
3345 add = true;
3346 index = true;
3347 wback = false;
3348 break;
3349 default:
3350 return false;
3351 }
3352 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3353 if (!success)
3354 return false;
3355 if (add)
3356 offset_addr = base + imm32;
3357 else
3358 offset_addr = base - imm32;
3359
3360 address = (index ? offset_addr : base);
3361
3362 if (wback)
3363 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003364 EmulateInstruction::Context ctx;
3365 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3366 Register dwarf_reg;
3367 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3368 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3369
Johnny Chenef21b592011-02-10 01:52:38 +00003370 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3371 return false;
3372 }
3373
3374 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003375 EmulateInstruction::Context context;
3376 context.type = EmulateInstruction::eContextImmediate;
3377 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003378
3379 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003380 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003381 if (!success)
3382 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003383
3384 if (Rt == 15)
3385 {
3386 if (Bits32(address, 1, 0) == 0)
3387 {
Johnny Chen668b4512011-02-15 21:08:58 +00003388 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003389 return false;
3390 }
3391 else
3392 return false;
3393 }
3394 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3395 {
3396 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3397 return false;
3398 }
3399 else
3400 return false;
3401 }
3402 return true;
3403}
3404
Caroline Ticeaf556562011-02-15 18:42:15 +00003405// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3406// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3407// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003408bool
3409EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3410{
3411#if 0
3412 if ConditionPassed() then
3413 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3414 address = R[n];
3415
3416 for i = 0 to 14
3417 if registers<i> == ’1’ then
3418 if i == n && wback && i != LowestSetBit(registers) then
3419 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3420 else
3421 MemA[address,4] = R[i];
3422 address = address + 4;
3423
3424 if registers<15> == ’1’ then // Only possible for encoding A1
3425 MemA[address,4] = PCStoreValue();
3426 if wback then R[n] = R[n] + 4*BitCount(registers);
3427#endif
3428
3429 bool success = false;
3430 const uint32_t opcode = OpcodeAsUnsigned (&success);
3431 if (!success)
3432 return false;
3433
3434 if (ConditionPassed ())
3435 {
3436 uint32_t n;
3437 uint32_t registers = 0;
3438 bool wback;
3439 const uint32_t addr_byte_size = GetAddressByteSize();
3440
3441 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3442 switch (encoding)
3443 {
3444 case eEncodingT1:
3445 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3446 n = Bits32 (opcode, 10, 8);
3447 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003448 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003449 wback = true;
3450
3451 // if BitCount(registers) < 1 then UNPREDICTABLE;
3452 if (BitCount (registers) < 1)
3453 return false;
3454
3455 break;
3456
3457 case eEncodingT2:
3458 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3459 n = Bits32 (opcode, 19, 16);
3460 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003461 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003462 wback = BitIsSet (opcode, 21);
3463
3464 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3465 if ((n == 15) || (BitCount (registers) < 2))
3466 return false;
3467
3468 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3469 if (wback && BitIsSet (registers, n))
3470 return false;
3471
3472 break;
3473
3474 case eEncodingA1:
3475 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3476 n = Bits32 (opcode, 19, 16);
3477 registers = Bits32 (opcode, 15, 0);
3478 wback = BitIsSet (opcode, 21);
3479
3480 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3481 if ((n == 15) || (BitCount (registers) < 1))
3482 return false;
3483
3484 break;
3485
3486 default:
3487 return false;
3488 }
3489
3490 // address = R[n];
3491 int32_t offset = 0;
3492 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3493 if (!success)
3494 return false;
3495
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003496 EmulateInstruction::Context context;
3497 context.type = EmulateInstruction::eContextRegisterStore;
3498 Register base_reg;
3499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003500
3501 // for i = 0 to 14
3502 for (int i = 0; i < 14; ++i)
3503 {
3504 int lowest_set_bit = 14;
3505 // if registers<i> == ’1’ then
3506 if (BitIsSet (registers, i))
3507 {
3508 if (i < lowest_set_bit)
3509 lowest_set_bit = i;
3510 // if i == n && wback && i != LowestSetBit(registers) then
3511 if ((i == n) && wback && (i != lowest_set_bit))
3512 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3513 WriteBits32UnknownToMemory (address + offset);
3514 else
3515 {
3516 // MemA[address,4] = R[i];
3517 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3518 if (!success)
3519 return false;
3520
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003521 Register data_reg;
3522 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3523 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003524 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003525 return false;
3526 }
3527
3528 // address = address + 4;
3529 offset += addr_byte_size;
3530 }
3531 }
3532
3533 // if registers<15> == ’1’ then // Only possible for encoding A1
3534 // MemA[address,4] = PCStoreValue();
3535 if (BitIsSet (registers, 15))
3536 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003537 Register pc_reg;
3538 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3539 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003540 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3541 if (!success)
3542 return false;
3543
Caroline Ticecc96eb52011-02-17 19:20:40 +00003544 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003545 return false;
3546 }
3547
3548 // if wback then R[n] = R[n] + 4*BitCount(registers);
3549 if (wback)
3550 {
3551 offset = addr_byte_size * BitCount (registers);
3552 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003553 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003554 addr_t data = address + offset;
3555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3556 return false;
3557 }
3558 }
3559 return true;
3560}
3561
Caroline Ticeaf556562011-02-15 18:42:15 +00003562// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3563// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3564// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003565bool
3566EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3567{
3568#if 0
3569 if ConditionPassed() then
3570 EncodingSpecificOperations();
3571 address = R[n] - 4*BitCount(registers) + 4;
3572
3573 for i = 0 to 14
3574 if registers<i> == ’1’ then
3575 if i == n && wback && i != LowestSetBit(registers) then
3576 MemA[address,4] = bits(32) UNKNOWN;
3577 else
3578 MemA[address,4] = R[i];
3579 address = address + 4;
3580
3581 if registers<15> == ’1’ then
3582 MemA[address,4] = PCStoreValue();
3583
3584 if wback then R[n] = R[n] - 4*BitCount(registers);
3585#endif
3586
3587 bool success = false;
3588 const uint32_t opcode = OpcodeAsUnsigned (&success);
3589 if (!success)
3590 return false;
3591
3592 if (ConditionPassed ())
3593 {
3594 uint32_t n;
3595 uint32_t registers = 0;
3596 bool wback;
3597 const uint32_t addr_byte_size = GetAddressByteSize();
3598
3599 // EncodingSpecificOperations();
3600 switch (encoding)
3601 {
3602 case eEncodingA1:
3603 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3604 n = Bits32 (opcode, 19, 16);
3605 registers = Bits32 (opcode, 15, 0);
3606 wback = BitIsSet (opcode, 21);
3607
3608 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3609 if ((n == 15) || (BitCount (registers) < 1))
3610 return false;
3611 break;
3612 default:
3613 return false;
3614 }
3615
3616 // address = R[n] - 4*BitCount(registers) + 4;
3617 int32_t offset = 0;
3618 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3619 if (!success)
3620 return false;
3621
3622 address = address - (addr_byte_size * BitCount (registers)) + 4;
3623
3624 EmulateInstruction::Context context;
3625 context.type = EmulateInstruction::eContextRegisterStore;
3626 Register base_reg;
3627 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3628
3629 // for i = 0 to 14
3630 for (int i = 0; i < 14; ++i)
3631 {
3632 int lowest_bit_set = 14;
3633 // if registers<i> == ’1’ then
3634 if (BitIsSet (registers, i))
3635 {
3636 if (i < lowest_bit_set)
3637 lowest_bit_set = i;
3638 //if i == n && wback && i != LowestSetBit(registers) then
3639 if ((i == n) && wback && (i != lowest_bit_set))
3640 // MemA[address,4] = bits(32) UNKNOWN;
3641 WriteBits32UnknownToMemory (address + offset);
3642 else
3643 {
3644 // MemA[address,4] = R[i];
3645 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3646 if (!success)
3647 return false;
3648
3649 Register data_reg;
3650 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3651 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003652 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003653 return false;
3654 }
3655
3656 // address = address + 4;
3657 offset += addr_byte_size;
3658 }
3659 }
3660
3661 // if registers<15> == ’1’ then
3662 // MemA[address,4] = PCStoreValue();
3663 if (BitIsSet (registers, 15))
3664 {
3665 Register pc_reg;
3666 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3667 context.SetRegisterPlusOffset (pc_reg, 8);
3668 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3669 if (!success)
3670 return false;
3671
Caroline Ticecc96eb52011-02-17 19:20:40 +00003672 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003673 return false;
3674 }
3675
3676 // if wback then R[n] = R[n] - 4*BitCount(registers);
3677 if (wback)
3678 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003679 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003680 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3681 context.SetImmediateSigned (offset);
3682 addr_t data = address + offset;
3683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3684 return false;
3685 }
3686 }
3687 return true;
3688}
3689
Caroline Ticeaf556562011-02-15 18:42:15 +00003690// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3691// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3692// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003693bool
3694EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3695{
3696#if 0
3697 if ConditionPassed() then
3698 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3699 address = R[n] - 4*BitCount(registers);
3700
3701 for i = 0 to 14
3702 if registers<i> == ’1’ then
3703 if i == n && wback && i != LowestSetBit(registers) then
3704 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3705 else
3706 MemA[address,4] = R[i];
3707 address = address + 4;
3708
3709 if registers<15> == ’1’ then // Only possible for encoding A1
3710 MemA[address,4] = PCStoreValue();
3711
3712 if wback then R[n] = R[n] - 4*BitCount(registers);
3713#endif
3714
3715
3716 bool success = false;
3717 const uint32_t opcode = OpcodeAsUnsigned (&success);
3718 if (!success)
3719 return false;
3720
3721 if (ConditionPassed ())
3722 {
3723 uint32_t n;
3724 uint32_t registers = 0;
3725 bool wback;
3726 const uint32_t addr_byte_size = GetAddressByteSize();
3727
3728 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3729 switch (encoding)
3730 {
3731 case eEncodingT1:
3732 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3733 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3734 {
3735 // See PUSH
3736 }
3737 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3738 n = Bits32 (opcode, 19, 16);
3739 registers = Bits32 (opcode, 15, 0);
3740 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3741 wback = BitIsSet (opcode, 21);
3742 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3743 if ((n == 15) || BitCount (registers) < 2)
3744 return false;
3745 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3746 if (wback && BitIsSet (registers, n))
3747 return false;
3748 break;
3749
3750 case eEncodingA1:
3751 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3752 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3753 {
3754 // See Push
3755 }
3756 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3757 n = Bits32 (opcode, 19, 16);
3758 registers = Bits32 (opcode, 15, 0);
3759 wback = BitIsSet (opcode, 21);
3760 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3761 if ((n == 15) || BitCount (registers) < 1)
3762 return false;
3763 break;
3764
3765 default:
3766 return false;
3767 }
3768
3769 // address = R[n] - 4*BitCount(registers);
3770
3771 int32_t offset = 0;
3772 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3773 if (!success)
3774 return false;
3775
3776 address = address - (addr_byte_size * BitCount (registers));
3777
3778 EmulateInstruction::Context context;
3779 context.type = EmulateInstruction::eContextRegisterStore;
3780 Register base_reg;
3781 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3782
3783 // for i = 0 to 14
3784 for (int i = 0; i < 14; ++i)
3785 {
3786 uint32_t lowest_set_bit = 14;
3787 // if registers<i> == ’1’ then
3788 if (BitIsSet (registers, i))
3789 {
3790 if (i < lowest_set_bit)
3791 lowest_set_bit = i;
3792 // if i == n && wback && i != LowestSetBit(registers) then
3793 if ((i == n) && wback && (i != lowest_set_bit))
3794 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3795 WriteBits32UnknownToMemory (address + offset);
3796 else
3797 {
3798 // MemA[address,4] = R[i];
3799 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3800 if (!success)
3801 return false;
3802
3803 Register data_reg;
3804 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3805 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003806 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003807 return false;
3808 }
3809
3810 // address = address + 4;
3811 offset += addr_byte_size;
3812 }
3813 }
3814
3815 // if registers<15> == ’1’ then // Only possible for encoding A1
3816 // MemA[address,4] = PCStoreValue();
3817 if (BitIsSet (registers, 15))
3818 {
3819 Register pc_reg;
3820 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3821 context.SetRegisterPlusOffset (pc_reg, 8);
3822 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3823 if (!success)
3824 return false;
3825
Caroline Ticecc96eb52011-02-17 19:20:40 +00003826 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003827 return false;
3828 }
3829
3830 // if wback then R[n] = R[n] - 4*BitCount(registers);
3831 if (wback)
3832 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003833 offset = (addr_byte_size * BitCount (registers)) * -1;
3834 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3835 context.SetImmediateSigned (offset);
3836 addr_t data = address + offset;
3837 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3838 return false;
3839 }
3840 }
3841 return true;
3842}
3843
3844// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3845// from a base register. The consecutive memory locations start just above this address, and the address of the last
3846// of those locations can optionally be written back to the base register.
3847bool
3848EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3849{
3850#if 0
3851 if ConditionPassed() then
3852 EncodingSpecificOperations();
3853 address = R[n] + 4;
3854
3855 for i = 0 to 14
3856 if registers<i> == ’1’ then
3857 if i == n && wback && i != LowestSetBit(registers) then
3858 MemA[address,4] = bits(32) UNKNOWN;
3859 else
3860 MemA[address,4] = R[i];
3861 address = address + 4;
3862
3863 if registers<15> == ’1’ then
3864 MemA[address,4] = PCStoreValue();
3865
3866 if wback then R[n] = R[n] + 4*BitCount(registers);
3867#endif
3868
3869 bool success = false;
3870 const uint32_t opcode = OpcodeAsUnsigned (&success);
3871 if (!success)
3872 return false;
3873
3874 if (ConditionPassed())
3875 {
3876 uint32_t n;
3877 uint32_t registers = 0;
3878 bool wback;
3879 const uint32_t addr_byte_size = GetAddressByteSize();
3880
3881 // EncodingSpecificOperations();
3882 switch (encoding)
3883 {
3884 case eEncodingA1:
3885 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3886 n = Bits32 (opcode, 19, 16);
3887 registers = Bits32 (opcode, 15, 0);
3888 wback = BitIsSet (opcode, 21);
3889
3890 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3891 if ((n == 15) && (BitCount (registers) < 1))
3892 return false;
3893 break;
3894 default:
3895 return false;
3896 }
3897 // address = R[n] + 4;
3898
3899 int32_t offset = 0;
3900 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3901 if (!success)
3902 return false;
3903
3904 address = address + addr_byte_size;
3905
3906 EmulateInstruction::Context context;
3907 context.type = EmulateInstruction::eContextRegisterStore;
3908 Register base_reg;
3909 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3910
3911 uint32_t lowest_set_bit = 14;
3912 // for i = 0 to 14
3913 for (int i = 0; i < 14; ++i)
3914 {
3915 // if registers<i> == ’1’ then
3916 if (BitIsSet (registers, i))
3917 {
3918 if (i < lowest_set_bit)
3919 lowest_set_bit = i;
3920 // if i == n && wback && i != LowestSetBit(registers) then
3921 if ((i == n) && wback && (i != lowest_set_bit))
3922 // MemA[address,4] = bits(32) UNKNOWN;
3923 WriteBits32UnknownToMemory (address + offset);
3924 // else
3925 else
3926 {
3927 // MemA[address,4] = R[i];
3928 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3929 if (!success)
3930 return false;
3931
3932 Register data_reg;
3933 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3934 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003935 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003936 return false;
3937 }
3938
3939 // address = address + 4;
3940 offset += addr_byte_size;
3941 }
3942 }
3943
3944 // if registers<15> == ’1’ then
3945 // MemA[address,4] = PCStoreValue();
3946 if (BitIsSet (registers, 15))
3947 {
3948 Register pc_reg;
3949 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3950 context.SetRegisterPlusOffset (pc_reg, 8);
3951 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3952 if (!success)
3953 return false;
3954
Caroline Ticecc96eb52011-02-17 19:20:40 +00003955 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003956 return false;
3957 }
3958
3959 // if wback then R[n] = R[n] + 4*BitCount(registers);
3960 if (wback)
3961 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003962 offset = addr_byte_size * BitCount (registers);
3963 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3964 context.SetImmediateSigned (offset);
3965 addr_t data = address + offset;
3966 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3967 return false;
3968 }
3969 }
3970 return true;
3971}
Caroline Tice7fac8572011-02-15 22:53:54 +00003972
3973// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3974// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3975bool
3976EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3977{
3978#if 0
3979 if ConditionPassed() then
3980 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3981 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3982 address = if index then offset_addr else R[n];
3983 if UnalignedSupport() || address<1:0> == ’00’ then
3984 MemU[address,4] = R[t];
3985 else // Can only occur before ARMv7
3986 MemU[address,4] = bits(32) UNKNOWN;
3987 if wback then R[n] = offset_addr;
3988#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003989
Caroline Tice7fac8572011-02-15 22:53:54 +00003990 bool success = false;
3991 const uint32_t opcode = OpcodeAsUnsigned (&success);
3992 if (!success)
3993 return false;
3994
3995 if (ConditionPassed())
3996 {
3997 const uint32_t addr_byte_size = GetAddressByteSize();
3998
3999 uint32_t t;
4000 uint32_t n;
4001 uint32_t imm32;
4002 bool index;
4003 bool add;
4004 bool wback;
4005 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4006 switch (encoding)
4007 {
4008 case eEncodingT1:
4009 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4010 t = Bits32 (opcode, 2, 0);
4011 n = Bits32 (opcode, 5, 3);
4012 imm32 = Bits32 (opcode, 10, 6) << 2;
4013
4014 // index = TRUE; add = TRUE; wback = FALSE;
4015 index = true;
4016 add = false;
4017 wback = false;
4018 break;
4019
4020 case eEncodingT2:
4021 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4022 t = Bits32 (opcode, 10, 8);
4023 n = 13;
4024 imm32 = Bits32 (opcode, 7, 0) << 2;
4025
4026 // index = TRUE; add = TRUE; wback = FALSE;
4027 index = true;
4028 add = true;
4029 wback = false;
4030 break;
4031
4032 case eEncodingT3:
4033 // if Rn == ’1111’ then UNDEFINED;
4034 if (Bits32 (opcode, 19, 16) == 15)
4035 return false;
4036
4037 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4038 t = Bits32 (opcode, 15, 12);
4039 n = Bits32 (opcode, 19, 16);
4040 imm32 = Bits32 (opcode, 11, 0);
4041
4042 // index = TRUE; add = TRUE; wback = FALSE;
4043 index = true;
4044 add = true;
4045 wback = false;
4046
4047 // if t == 15 then UNPREDICTABLE;
4048 if (t == 15)
4049 return false;
4050 break;
4051
4052 case eEncodingT4:
4053 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4054 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4055 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4056 if ((Bits32 (opcode, 19, 16) == 15)
4057 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4058 return false;
4059
4060 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4061 t = Bits32 (opcode, 15, 12);
4062 n = Bits32 (opcode, 19, 16);
4063 imm32 = Bits32 (opcode, 7, 0);
4064
4065 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4066 index = BitIsSet (opcode, 10);
4067 add = BitIsSet (opcode, 9);
4068 wback = BitIsSet (opcode, 8);
4069
4070 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4071 if ((t == 15) || (wback && (n == t)))
4072 return false;
4073 break;
4074
4075 default:
4076 return false;
4077 }
4078
4079 addr_t offset_addr;
4080 addr_t address;
4081
4082 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4083 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4084 if (!success)
4085 return false;
4086
4087 if (add)
4088 offset_addr = base_address + imm32;
4089 else
4090 offset_addr = base_address - imm32;
4091
4092 // address = if index then offset_addr else R[n];
4093 if (index)
4094 address = offset_addr;
4095 else
4096 address = base_address;
4097
4098 EmulateInstruction::Context context;
4099 context.type = eContextRegisterStore;
4100 Register base_reg;
4101 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4102
4103 // if UnalignedSupport() || address<1:0> == ’00’ then
4104 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4105 {
4106 // MemU[address,4] = R[t];
4107 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4108 if (!success)
4109 return false;
4110
4111 Register data_reg;
4112 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4113 int32_t offset = address - base_address;
4114 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004115 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004116 return false;
4117 }
4118 else
4119 {
4120 // MemU[address,4] = bits(32) UNKNOWN;
4121 WriteBits32UnknownToMemory (address);
4122 }
4123
4124 // if wback then R[n] = offset_addr;
4125 if (wback)
4126 {
4127 context.type = eContextRegisterLoad;
4128 context.SetAddress (offset_addr);
4129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4130 return false;
4131 }
4132 }
4133 return true;
4134}
Caroline Ticeaf556562011-02-15 18:42:15 +00004135
Caroline Tice3fd63e92011-02-16 00:33:43 +00004136// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4137// word from a register to memory. The offset register value can optionally be shifted.
4138bool
4139EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4140{
4141#if 0
4142 if ConditionPassed() then
4143 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4144 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4145 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4146 address = if index then offset_addr else R[n];
4147 if t == 15 then // Only possible for encoding A1
4148 data = PCStoreValue();
4149 else
4150 data = R[t];
4151 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4152 MemU[address,4] = data;
4153 else // Can only occur before ARMv7
4154 MemU[address,4] = bits(32) UNKNOWN;
4155 if wback then R[n] = offset_addr;
4156#endif
4157
4158 bool success = false;
4159 const uint32_t opcode = OpcodeAsUnsigned (&success);
4160 if (!success)
4161 return false;
4162
4163 if (ConditionPassed())
4164 {
4165 const uint32_t addr_byte_size = GetAddressByteSize();
4166
4167 uint32_t t;
4168 uint32_t n;
4169 uint32_t m;
4170 ARM_ShifterType shift_t;
4171 uint32_t shift_n;
4172 bool index;
4173 bool add;
4174 bool wback;
4175
4176 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4177 switch (encoding)
4178 {
4179 case eEncodingT1:
4180 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4181 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4182 t = Bits32 (opcode, 2, 0);
4183 n = Bits32 (opcode, 5, 3);
4184 m = Bits32 (opcode, 8, 6);
4185
4186 // index = TRUE; add = TRUE; wback = FALSE;
4187 index = true;
4188 add = true;
4189 wback = false;
4190
4191 // (shift_t, shift_n) = (SRType_LSL, 0);
4192 shift_t = SRType_LSL;
4193 shift_n = 0;
4194 break;
4195
4196 case eEncodingT2:
4197 // if Rn == ’1111’ then UNDEFINED;
4198 if (Bits32 (opcode, 19, 16) == 15)
4199 return false;
4200
4201 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4202 t = Bits32 (opcode, 15, 12);
4203 n = Bits32 (opcode, 19, 16);
4204 m = Bits32 (opcode, 3, 0);
4205
4206 // index = TRUE; add = TRUE; wback = FALSE;
4207 index = true;
4208 add = true;
4209 wback = false;
4210
4211 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4212 shift_t = SRType_LSL;
4213 shift_n = Bits32 (opcode, 5, 4);
4214
4215 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4216 if ((t == 15) || (BadReg (m)))
4217 return false;
4218 break;
4219
4220 case eEncodingA1:
4221 {
4222 // if P == ’0’ && W == ’1’ then SEE STRT;
4223 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4224 t = Bits32 (opcode, 15, 12);
4225 n = Bits32 (opcode, 19, 16);
4226 m = Bits32 (opcode, 3, 0);
4227
4228 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4229 index = BitIsSet (opcode, 24);
4230 add = BitIsSet (opcode, 23);
4231 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4232
4233 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4234 uint32_t typ = Bits32 (opcode, 6, 5);
4235 uint32_t imm5 = Bits32 (opcode, 11, 7);
4236 shift_n = DecodeImmShift(typ, imm5, shift_t);
4237
4238 // if m == 15 then UNPREDICTABLE;
4239 if (m == 15)
4240 return false;
4241
4242 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4243 if (wback && ((n == 15) || (n == t)))
4244 return false;
4245
4246 break;
4247 }
4248 default:
4249 return false;
4250 }
4251
4252 addr_t offset_addr;
4253 addr_t address;
4254 int32_t offset = 0;
4255
4256 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4257 if (!success)
4258 return false;
4259
4260 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4261 if (!success)
4262 return false;
4263
4264 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004265 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004266
4267 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4268 if (add)
4269 offset_addr = base_address + offset;
4270 else
4271 offset_addr = base_address - offset;
4272
4273 // address = if index then offset_addr else R[n];
4274 if (index)
4275 address = offset_addr;
4276 else
4277 address = base_address;
4278
4279 uint32_t data;
4280 // if t == 15 then // Only possible for encoding A1
4281 if (t == 15)
4282 // data = PCStoreValue();
4283 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4284 else
4285 // data = R[t];
4286 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4287
4288 if (!success)
4289 return false;
4290
4291 EmulateInstruction::Context context;
4292 context.type = eContextRegisterStore;
4293
4294 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4295 if (UnalignedSupport ()
4296 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4297 || CurrentInstrSet() == eModeARM)
4298 {
4299 // MemU[address,4] = data;
4300
4301 Register base_reg;
4302 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4303
4304 Register data_reg;
4305 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4306
4307 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004308 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004309 return false;
4310
4311 }
4312 else
4313 // MemU[address,4] = bits(32) UNKNOWN;
4314 WriteBits32UnknownToMemory (address);
4315
4316 // if wback then R[n] = offset_addr;
4317 if (wback)
4318 {
4319 context.type = eContextRegisterLoad;
4320 context.SetAddress (offset_addr);
4321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4322 return false;
4323 }
4324
4325 }
4326 return true;
4327}
Caroline Tice73a29de2011-02-16 20:22:22 +00004328
4329bool
4330EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4331{
4332#if 0
4333 if ConditionPassed() then
4334 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4335 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4336 address = if index then offset_addr else R[n];
4337 MemU[address,1] = R[t]<7:0>;
4338 if wback then R[n] = offset_addr;
4339#endif
4340
4341
4342 bool success = false;
4343 const uint32_t opcode = OpcodeAsUnsigned (&success);
4344 if (!success)
4345 return false;
4346
4347 if (ConditionPassed ())
4348 {
4349 uint32_t t;
4350 uint32_t n;
4351 uint32_t imm32;
4352 bool index;
4353 bool add;
4354 bool wback;
4355 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4356 switch (encoding)
4357 {
4358 case eEncodingT1:
4359 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4360 t = Bits32 (opcode, 2, 0);
4361 n = Bits32 (opcode, 5, 3);
4362 imm32 = Bits32 (opcode, 10, 6);
4363
4364 // index = TRUE; add = TRUE; wback = FALSE;
4365 index = true;
4366 add = true;
4367 wback = false;
4368 break;
4369
4370 case eEncodingT2:
4371 // if Rn == ’1111’ then UNDEFINED;
4372 if (Bits32 (opcode, 19, 16) == 15)
4373 return false;
4374
4375 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4376 t = Bits32 (opcode, 15, 12);
4377 n = Bits32 (opcode, 19, 16);
4378 imm32 = Bits32 (opcode, 11, 0);
4379
4380 // index = TRUE; add = TRUE; wback = FALSE;
4381 index = true;
4382 add = true;
4383 wback = false;
4384
4385 // if BadReg(t) then UNPREDICTABLE;
4386 if (BadReg (t))
4387 return false;
4388 break;
4389
4390 case eEncodingT3:
4391 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4392 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4393 if (Bits32 (opcode, 19, 16) == 15)
4394 return false;
4395
4396 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4397 t = Bits32 (opcode, 15, 12);
4398 n = Bits32 (opcode, 19, 16);
4399 imm32 = Bits32 (opcode, 7, 0);
4400
4401 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4402 index = BitIsSet (opcode, 10);
4403 add = BitIsSet (opcode, 9);
4404 wback = BitIsSet (opcode, 8);
4405
4406 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4407 if ((BadReg (t)) || (wback && (n == t)))
4408 return false;
4409 break;
4410
4411 default:
4412 return false;
4413 }
4414
4415 addr_t offset_addr;
4416 addr_t address;
4417 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4418 if (!success)
4419 return false;
4420
4421 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4422 if (add)
4423 offset_addr = base_address + imm32;
4424 else
4425 offset_addr = base_address - imm32;
4426
4427 // address = if index then offset_addr else R[n];
4428 if (index)
4429 address = offset_addr;
4430 else
4431 address = base_address;
4432
Caroline Ticecc96eb52011-02-17 19:20:40 +00004433 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004434 Register base_reg;
4435 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4436
4437 Register data_reg;
4438 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4439
4440 EmulateInstruction::Context context;
4441 context.type = eContextRegisterStore;
4442 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4443
4444 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4445 if (!success)
4446 return false;
4447
4448 data = Bits32 (data, 7, 0);
4449
Caroline Ticecc96eb52011-02-17 19:20:40 +00004450 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004451 return false;
4452
4453 // if wback then R[n] = offset_addr;
4454 if (wback)
4455 {
4456 context.type = eContextRegisterLoad;
4457 context.SetAddress (offset_addr);
4458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4459 return false;
4460 }
4461
4462 }
4463
4464 return true;
4465}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004466
Johnny Chen157b9592011-02-18 21:13:05 +00004467// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4468// and writes the result to the destination register. It can optionally update the condition flags
4469// based on the result.
4470bool
4471EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4472{
4473#if 0
4474 // ARM pseudo code...
4475 if ConditionPassed() then
4476 EncodingSpecificOperations();
4477 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4478 if d == 15 then // Can only occur for ARM encoding
4479 ALUWritePC(result); // setflags is always FALSE here
4480 else
4481 R[d] = result;
4482 if setflags then
4483 APSR.N = result<31>;
4484 APSR.Z = IsZeroBit(result);
4485 APSR.C = carry;
4486 APSR.V = overflow;
4487#endif
4488
4489 bool success = false;
4490 const uint32_t opcode = OpcodeAsUnsigned (&success);
4491 if (!success)
4492 return false;
4493
4494 if (ConditionPassed())
4495 {
4496 uint32_t Rd, Rn;
4497 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4498 bool setflags;
4499 switch (encoding)
4500 {
4501 case eEncodingT1:
4502 Rd = Bits32(opcode, 11, 8);
4503 Rn = Bits32(opcode, 19, 16);
4504 setflags = BitIsSet(opcode, 20);
4505 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4506 if (BadReg(Rd) || BadReg(Rn))
4507 return false;
4508 break;
4509 case eEncodingA1:
4510 Rd = Bits32(opcode, 15, 12);
4511 Rn = Bits32(opcode, 19, 16);
4512 setflags = BitIsSet(opcode, 20);
4513 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4514 // TODO: Emulate SUBS PC, LR and related instructions.
4515 if (Rd == 15 && setflags)
4516 return false;
4517 break;
4518 default:
4519 return false;
4520 }
4521
4522 // Read the first operand.
4523 int32_t val1 = ReadCoreReg(Rn, &success);
4524 if (!success)
4525 return false;
4526
4527 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4528
4529 EmulateInstruction::Context context;
4530 context.type = EmulateInstruction::eContextImmediate;
4531 context.SetNoArgs ();
4532
4533 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4534 return false;
4535 }
4536 return true;
4537}
4538
4539// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4540// register value, and writes the result to the destination register. It can optionally update the
4541// condition flags based on the result.
4542bool
4543EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4544{
4545#if 0
4546 // ARM pseudo code...
4547 if ConditionPassed() then
4548 EncodingSpecificOperations();
4549 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4550 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4551 if d == 15 then // Can only occur for ARM encoding
4552 ALUWritePC(result); // setflags is always FALSE here
4553 else
4554 R[d] = result;
4555 if setflags then
4556 APSR.N = result<31>;
4557 APSR.Z = IsZeroBit(result);
4558 APSR.C = carry;
4559 APSR.V = overflow;
4560#endif
4561
4562 bool success = false;
4563 const uint32_t opcode = OpcodeAsUnsigned (&success);
4564 if (!success)
4565 return false;
4566
4567 if (ConditionPassed())
4568 {
4569 uint32_t Rd, Rn, Rm;
4570 ARM_ShifterType shift_t;
4571 uint32_t shift_n; // the shift applied to the value read from Rm
4572 bool setflags;
4573 switch (encoding)
4574 {
4575 case eEncodingT1:
4576 Rd = Rn = Bits32(opcode, 2, 0);
4577 Rm = Bits32(opcode, 5, 3);
4578 setflags = !InITBlock();
4579 shift_t = SRType_LSL;
4580 shift_n = 0;
4581 case eEncodingT2:
4582 Rd = Bits32(opcode, 11, 8);
4583 Rn = Bits32(opcode, 19, 16);
4584 Rm = Bits32(opcode, 3, 0);
4585 setflags = BitIsSet(opcode, 20);
4586 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
4587 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4588 return false;
4589 break;
4590 case eEncodingA1:
4591 Rd = Bits32(opcode, 15, 12);
4592 Rn = Bits32(opcode, 19, 16);
4593 Rm = Bits32(opcode, 3, 0);
4594 setflags = BitIsSet(opcode, 20);
4595 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4596 // TODO: Emulate SUBS PC, LR and related instructions.
4597 if (Rd == 15 && setflags)
4598 return false;
4599 break;
4600 default:
4601 return false;
4602 }
4603
4604 // Read the first operand.
4605 int32_t val1 = ReadCoreReg(Rn, &success);
4606 if (!success)
4607 return false;
4608
4609 // Read the second operand.
4610 int32_t val2 = ReadCoreReg(Rm, &success);
4611 if (!success)
4612 return false;
4613
4614 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4615 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4616
4617 EmulateInstruction::Context context;
4618 context.type = EmulateInstruction::eContextImmediate;
4619 context.SetNoArgs ();
4620
4621 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4622 return false;
4623 }
4624 return true;
4625}
4626
Johnny Chene97c0d52011-02-18 19:32:20 +00004627// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4628// to the destination register. It can optionally update the condition flags based on the result.
4629bool
4630EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4631{
4632#if 0
4633 // ARM pseudo code...
4634 if ConditionPassed() then
4635 EncodingSpecificOperations();
4636 result = R[n] AND imm32;
4637 if d == 15 then // Can only occur for ARM encoding
4638 ALUWritePC(result); // setflags is always FALSE here
4639 else
4640 R[d] = result;
4641 if setflags then
4642 APSR.N = result<31>;
4643 APSR.Z = IsZeroBit(result);
4644 APSR.C = carry;
4645 // APSR.V unchanged
4646#endif
4647
4648 bool success = false;
4649 const uint32_t opcode = OpcodeAsUnsigned (&success);
4650 if (!success)
4651 return false;
4652
4653 if (ConditionPassed())
4654 {
4655 uint32_t Rd, Rn;
4656 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4657 bool setflags;
4658 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4659 switch (encoding)
4660 {
4661 case eEncodingT1:
4662 Rd = Bits32(opcode, 11, 8);
4663 Rn = Bits32(opcode, 19, 16);
4664 setflags = BitIsSet(opcode, 20);
4665 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004666 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004667 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004668 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004669 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4670 return false;
4671 break;
4672 case eEncodingA1:
4673 Rd = Bits32(opcode, 15, 12);
4674 Rn = Bits32(opcode, 19, 16);
4675 setflags = BitIsSet(opcode, 20);
4676 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4677 // TODO: Emulate SUBS PC, LR and related instructions.
4678 if (Rd == 15 && setflags)
4679 return false;
4680 break;
4681 default:
4682 return false;
4683 }
4684
Johnny Chene97c0d52011-02-18 19:32:20 +00004685 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004686 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004687 if (!success)
4688 return false;
4689
4690 uint32_t result = val1 & imm32;
4691
4692 EmulateInstruction::Context context;
4693 context.type = EmulateInstruction::eContextImmediate;
4694 context.SetNoArgs ();
4695
4696 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4697 return false;
4698 }
4699 return true;
4700}
4701
4702// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4703// and writes the result to the destination register. It can optionally update the condition flags
4704// based on the result.
4705bool
4706EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4707{
4708#if 0
4709 // ARM pseudo code...
4710 if ConditionPassed() then
4711 EncodingSpecificOperations();
4712 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4713 result = R[n] AND shifted;
4714 if d == 15 then // Can only occur for ARM encoding
4715 ALUWritePC(result); // setflags is always FALSE here
4716 else
4717 R[d] = result;
4718 if setflags then
4719 APSR.N = result<31>;
4720 APSR.Z = IsZeroBit(result);
4721 APSR.C = carry;
4722 // APSR.V unchanged
4723#endif
4724
4725 bool success = false;
4726 const uint32_t opcode = OpcodeAsUnsigned (&success);
4727 if (!success)
4728 return false;
4729
4730 if (ConditionPassed())
4731 {
4732 uint32_t Rd, Rn, Rm;
4733 ARM_ShifterType shift_t;
4734 uint32_t shift_n; // the shift applied to the value read from Rm
4735 bool setflags;
4736 uint32_t carry;
4737 switch (encoding)
4738 {
4739 case eEncodingT1:
4740 Rd = Rn = Bits32(opcode, 2, 0);
4741 Rm = Bits32(opcode, 5, 3);
4742 setflags = !InITBlock();
4743 shift_t = SRType_LSL;
4744 shift_n = 0;
4745 case eEncodingT2:
4746 Rd = Bits32(opcode, 11, 8);
4747 Rn = Bits32(opcode, 19, 16);
4748 Rm = Bits32(opcode, 3, 0);
4749 setflags = BitIsSet(opcode, 20);
Johnny Chen157b9592011-02-18 21:13:05 +00004750 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004751 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004752 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004753 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004754 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4755 return false;
4756 break;
4757 case eEncodingA1:
4758 Rd = Bits32(opcode, 15, 12);
4759 Rn = Bits32(opcode, 19, 16);
4760 Rm = Bits32(opcode, 3, 0);
4761 setflags = BitIsSet(opcode, 20);
4762 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4763 // TODO: Emulate SUBS PC, LR and related instructions.
4764 if (Rd == 15 && setflags)
4765 return false;
4766 break;
4767 default:
4768 return false;
4769 }
4770
Johnny Chene97c0d52011-02-18 19:32:20 +00004771 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004772 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004773 if (!success)
4774 return false;
4775
4776 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004777 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004778 if (!success)
4779 return false;
4780
4781 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4782 uint32_t result = val1 & shifted;
4783
4784 EmulateInstruction::Context context;
4785 context.type = EmulateInstruction::eContextImmediate;
4786 context.SetNoArgs ();
4787
4788 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4789 return false;
4790 }
4791 return true;
4792}
4793
Caroline Tice4d729c52011-02-18 00:55:53 +00004794// 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 +00004795// 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 +00004796bool
4797EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4798{
4799#if 0
4800 if ConditionPassed() then
4801 EncodingSpecificOperations();
4802 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4803 address = if index then offset_addr else R[n];
4804 data = MemU[address,4];
4805 if wback then R[n] = offset_addr;
4806 if t == 15 then
4807 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4808 elsif UnalignedSupport() || address<1:0> = ’00’ then
4809 R[t] = data;
4810 else // Can only apply before ARMv7
4811 R[t] = ROR(data, 8*UInt(address<1:0>));
4812#endif
4813
4814 bool success = false;
4815 const uint32_t opcode = OpcodeAsUnsigned (&success);
4816 if (!success)
4817 return false;
4818
4819 if (ConditionPassed ())
4820 {
4821 const uint32_t addr_byte_size = GetAddressByteSize();
4822
4823 uint32_t t;
4824 uint32_t n;
4825 uint32_t imm32;
4826 bool index;
4827 bool add;
4828 bool wback;
4829
4830 switch (encoding)
4831 {
4832 case eEncodingA1:
4833 // if Rn == ’1111’ then SEE LDR (literal);
4834 // if P == ’0’ && W == ’1’ then SEE LDRT;
4835 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4836 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4837 t = Bits32 (opcode, 15, 12);
4838 n = Bits32 (opcode, 19, 16);
4839 imm32 = Bits32 (opcode, 11, 0);
4840
4841 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4842 index = BitIsSet (opcode, 24);
4843 add = BitIsSet (opcode, 23);
4844 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4845
4846 // if wback && n == t then UNPREDICTABLE;
4847 if (wback && (n == t))
4848 return false;
4849
4850 break;
4851
4852 default:
4853 return false;
4854 }
4855
4856 addr_t address;
4857 addr_t offset_addr;
4858 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4859 if (!success)
4860 return false;
4861
4862 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4863 if (add)
4864 offset_addr = base_address + imm32;
4865 else
4866 offset_addr = base_address - imm32;
4867
4868 // address = if index then offset_addr else R[n];
4869 if (index)
4870 address = offset_addr;
4871 else
4872 address = base_address;
4873
4874 // data = MemU[address,4];
4875
4876 Register base_reg;
4877 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4878
4879 EmulateInstruction::Context context;
4880 context.type = eContextRegisterLoad;
4881 context.SetRegisterPlusOffset (base_reg, address - base_address);
4882
4883 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4884 if (!success)
4885 return false;
4886
4887 // if wback then R[n] = offset_addr;
4888 if (wback)
4889 {
4890 context.type = eContextAdjustBaseRegister;
4891 context.SetAddress (offset_addr);
4892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4893 return false;
4894 }
4895
4896 // if t == 15 then
4897 if (t == 15)
4898 {
4899 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4900 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4901 {
4902 // LoadWritePC (data);
4903 context.type = eContextRegisterLoad;
4904 context.SetRegisterPlusOffset (base_reg, address - base_address);
4905 LoadWritePC (context, data);
4906 }
4907 else
4908 return false;
4909 }
4910 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4911 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4912 {
4913 // R[t] = data;
4914 context.type = eContextRegisterLoad;
4915 context.SetRegisterPlusOffset (base_reg, address - base_address);
4916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4917 return false;
4918 }
4919 // else // Can only apply before ARMv7
4920 else
4921 {
4922 // R[t] = ROR(data, 8*UInt(address<1:0>));
4923 data = ROR (data, Bits32 (address, 1, 0));
4924 context.type = eContextRegisterLoad;
4925 context.SetImmediate (data);
4926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4927 return false;
4928 }
4929
4930 }
4931 return true;
4932}
4933
Caroline Ticefe479112011-02-18 18:52:37 +00004934// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4935// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4936bool
4937EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4938{
4939#if 0
4940 if ConditionPassed() then
4941 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4942 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4943 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4944 address = if index then offset_addr else R[n];
4945 data = MemU[address,4];
4946 if wback then R[n] = offset_addr;
4947 if t == 15 then
4948 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4949 elsif UnalignedSupport() || address<1:0> = ’00’ then
4950 R[t] = data;
4951 else // Can only apply before ARMv7
4952 if CurrentInstrSet() == InstrSet_ARM then
4953 R[t] = ROR(data, 8*UInt(address<1:0>));
4954 else
4955 R[t] = bits(32) UNKNOWN;
4956#endif
4957
4958 bool success = false;
4959 const uint32_t opcode = OpcodeAsUnsigned (&success);
4960 if (!success)
4961 return false;
4962
4963 if (ConditionPassed ())
4964 {
4965 const uint32_t addr_byte_size = GetAddressByteSize();
4966
4967 uint32_t t;
4968 uint32_t n;
4969 uint32_t m;
4970 bool index;
4971 bool add;
4972 bool wback;
4973 ARM_ShifterType shift_t;
4974 uint32_t shift_n;
4975
4976 switch (encoding)
4977 {
4978 case eEncodingT1:
4979 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4980 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4981 t = Bits32 (opcode, 2, 0);
4982 n = Bits32 (opcode, 5, 3);
4983 m = Bits32 (opcode, 8, 6);
4984
4985 // index = TRUE; add = TRUE; wback = FALSE;
4986 index = true;
4987 add = true;
4988 wback = false;
4989
4990 // (shift_t, shift_n) = (SRType_LSL, 0);
4991 shift_t = SRType_LSL;
4992 shift_n = 0;
4993
4994 break;
4995
4996 case eEncodingT2:
4997 // if Rn == ’1111’ then SEE LDR (literal);
4998 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4999 t = Bits32 (opcode, 15, 12);
5000 n = Bits32 (opcode, 19, 16);
5001 m = Bits32 (opcode, 3, 0);
5002
5003 // index = TRUE; add = TRUE; wback = FALSE;
5004 index = true;
5005 add = true;
5006 wback = false;
5007
5008 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5009 shift_t = SRType_LSL;
5010 shift_n = Bits32 (opcode, 5, 4);
5011
5012 // if BadReg(m) then UNPREDICTABLE;
5013 if (BadReg (m))
5014 return false;
5015
5016 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5017 if ((t == 15) && InITBlock() && !LastInITBlock())
5018 return false;
5019
5020 break;
5021
5022 case eEncodingA1:
5023 {
5024 // if P == ’0’ && W == ’1’ then SEE LDRT;
5025 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5026 t = Bits32 (opcode, 15, 12);
5027 n = Bits32 (opcode, 19, 16);
5028 m = Bits32 (opcode, 3, 0);
5029
5030 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5031 index = BitIsSet (opcode, 24);
5032 add = BitIsSet (opcode, 23);
5033 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5034
5035 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5036 uint32_t type = Bits32 (opcode, 6, 5);
5037 uint32_t imm5 = Bits32 (opcode, 11, 7);
5038 shift_n = DecodeImmShift (type, imm5, shift_t);
5039
5040 // if m == 15 then UNPREDICTABLE;
5041 if (m == 15)
5042 return false;
5043
5044 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5045 if (wback && ((n == 15) || (n == t)))
5046 return false;
5047 }
5048 break;
5049
5050
5051 default:
5052 return false;
5053 }
5054
5055 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5056 if (!success)
5057 return false;
5058
5059 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5060 if (!success)
5061 return false;
5062
5063 addr_t offset_addr;
5064 addr_t address;
5065
5066 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
5067 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
5068
5069 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5070 if (add)
5071 offset_addr = Rn + offset;
5072 else
5073 offset_addr = Rn - offset;
5074
5075 // address = if index then offset_addr else R[n];
5076 if (index)
5077 address = offset_addr;
5078 else
5079 address = Rn;
5080
5081 // data = MemU[address,4];
5082 Register base_reg;
5083 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5084
5085 EmulateInstruction::Context context;
5086 context.type = eContextRegisterLoad;
5087 context.SetRegisterPlusOffset (base_reg, address - Rn);
5088
5089 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5090 if (!success)
5091 return false;
5092
5093 // if wback then R[n] = offset_addr;
5094 if (wback)
5095 {
5096 context.type = eContextAdjustBaseRegister;
5097 context.SetAddress (offset_addr);
5098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5099 return false;
5100 }
5101
5102 // if t == 15 then
5103 if (t == 15)
5104 {
5105 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5106 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5107 {
5108 context.type = eContextRegisterLoad;
5109 context.SetRegisterPlusOffset (base_reg, address - Rn);
5110 LoadWritePC (context, data);
5111 }
5112 else
5113 return false;
5114 }
5115 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5116 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5117 {
5118 // R[t] = data;
5119 context.type = eContextRegisterLoad;
5120 context.SetRegisterPlusOffset (base_reg, address - Rn);
5121 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5122 return false;
5123 }
5124 else // Can only apply before ARMv7
5125 {
5126 // if CurrentInstrSet() == InstrSet_ARM then
5127 if (CurrentInstrSet () == eModeARM)
5128 {
5129 // R[t] = ROR(data, 8*UInt(address<1:0>));
5130 data = ROR (data, Bits32 (address, 1, 0));
5131 context.type = eContextRegisterLoad;
5132 context.SetImmediate (data);
5133 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5134 return false;
5135 }
5136 else
5137 {
5138 // R[t] = bits(32) UNKNOWN;
5139 WriteBits32Unknown (t);
5140 }
5141 }
5142 }
5143 return true;
5144}
Caroline Tice21b604b2011-02-18 21:06:04 +00005145
5146// LDRB (immediate, Thumb)
5147bool
5148EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5149{
5150#if 0
5151 if ConditionPassed() then
5152 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5153 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5154 address = if index then offset_addr else R[n];
5155 R[t] = ZeroExtend(MemU[address,1], 32);
5156 if wback then R[n] = offset_addr;
5157#endif
5158
5159 bool success = false;
5160 const uint32_t opcode = OpcodeAsUnsigned (&success);
5161 if (!success)
5162 return false;
5163
5164 if (ConditionPassed ())
5165 {
5166 uint32_t t;
5167 uint32_t n;
5168 uint32_t imm32;
5169 bool index;
5170 bool add;
5171 bool wback;
5172
5173 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5174 switch (encoding)
5175 {
5176 case eEncodingT1:
5177 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5178 t = Bits32 (opcode, 2, 0);
5179 n = Bits32 (opcode, 5, 3);
5180 imm32 = Bits32 (opcode, 10, 6);
5181
5182 // index = TRUE; add = TRUE; wback = FALSE;
5183 index = true;
5184 add = true;
5185 wback= false;
5186
5187 break;
5188
5189 case eEncodingT2:
5190 // if Rt == ’1111’ then SEE PLD;
5191 // if Rn == ’1111’ then SEE LDRB (literal);
5192 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5193 t = Bits32 (opcode, 15, 12);
5194 n = Bits32 (opcode, 19, 16);
5195 imm32 = Bits32 (opcode, 11, 0);
5196
5197 // index = TRUE; add = TRUE; wback = FALSE;
5198 index = true;
5199 add = true;
5200 wback = false;
5201
5202 // if t == 13 then UNPREDICTABLE;
5203 if (t == 13)
5204 return false;
5205
5206 break;
5207
5208 case eEncodingT3:
5209 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5210 // if Rn == ’1111’ then SEE LDRB (literal);
5211 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5212 // if P == ’0’ && W == ’0’ then UNDEFINED;
5213 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5214 return false;
5215
5216 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5217 t = Bits32 (opcode, 15, 12);
5218 n = Bits32 (opcode, 19, 16);
5219 imm32 = Bits32 (opcode, 7, 0);
5220
5221 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5222 index = BitIsSet (opcode, 10);
5223 add = BitIsSet (opcode, 9);
5224 wback = BitIsSet (opcode, 8);
5225
5226 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5227 if (BadReg (t) || (wback && (n == t)))
5228 return false;
5229
5230 break;
5231
5232 default:
5233 return false;
5234 }
5235
5236 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5237 if (!success)
5238 return false;
5239
5240 addr_t address;
5241 addr_t offset_addr;
5242
5243 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5244 if (add)
5245 offset_addr = Rn + imm32;
5246 else
5247 offset_addr = Rn - imm32;
5248
5249 // address = if index then offset_addr else R[n];
5250 if (index)
5251 address = offset_addr;
5252 else
5253 address = Rn;
5254
5255 // R[t] = ZeroExtend(MemU[address,1], 32);
5256 Register base_reg;
5257 Register data_reg;
5258 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5259 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5260
5261 EmulateInstruction::Context context;
5262 context.type = eContextRegisterLoad;
5263 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5264
5265 uint64_t data = MemURead (context, address, 1, 0, &success);
5266 if (!success)
5267 return false;
5268
5269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5270 return false;
5271
5272 // if wback then R[n] = offset_addr;
5273 if (wback)
5274 {
5275 context.type = eContextAdjustBaseRegister;
5276 context.SetAddress (offset_addr);
5277 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5278 return false;
5279 }
5280 }
5281 return true;
5282}
Caroline Ticef55261f2011-02-18 22:24:22 +00005283
5284// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5285// zero-extends it to form a 32-bit word and writes it to a register.
5286bool
5287EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5288{
5289#if 0
5290 if ConditionPassed() then
5291 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5292 base = Align(PC,4);
5293 address = if add then (base + imm32) else (base - imm32);
5294 R[t] = ZeroExtend(MemU[address,1], 32);
5295#endif
5296
5297 bool success = false;
5298 const uint32_t opcode = OpcodeAsUnsigned (&success);
5299 if (!success)
5300 return false;
5301
5302 if (ConditionPassed ())
5303 {
5304 uint32_t t;
5305 uint32_t imm32;
5306 bool add;
5307 switch (encoding)
5308 {
5309 case eEncodingT1:
5310 // if Rt == ’1111’ then SEE PLD;
5311 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5312 t = Bits32 (opcode, 15, 12);
5313 imm32 = Bits32 (opcode, 11, 0);
5314 add = BitIsSet (opcode, 23);
5315
5316 // if t == 13 then UNPREDICTABLE;
5317 if (t == 13)
5318 return false;
5319
5320 break;
5321
5322 case eEncodingA1:
5323 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5324 t = Bits32 (opcode, 15, 12);
5325 imm32 = Bits32 (opcode, 11, 0);
5326 add = BitIsSet (opcode, 23);
5327
5328 // if t == 15 then UNPREDICTABLE;
5329 if (t == 15)
5330 return false;
5331 break;
5332
5333 default:
5334 return false;
5335 }
5336
5337 // base = Align(PC,4);
5338 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5339 if (!success)
5340 return false;
5341
5342 uint32_t base = AlignPC (pc_val);
5343
5344 addr_t address;
5345 // address = if add then (base + imm32) else (base - imm32);
5346 if (add)
5347 address = base + imm32;
5348 else
5349 address = base - imm32;
5350
5351 // R[t] = ZeroExtend(MemU[address,1], 32);
5352 EmulateInstruction::Context context;
5353 context.type = eContextRelativeBranchImmediate;
5354 context.SetImmediate (address - base);
5355
5356 uint64_t data = MemURead (context, address, 1, 0, &success);
5357 if (!success)
5358 return false;
5359
5360 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5361 return false;
5362 }
5363 return true;
5364}
Caroline Tice30fec122011-02-18 23:52:21 +00005365
5366// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5367// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5368// optionally be shifted.
5369bool
5370EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5371{
5372#if 0
5373 if ConditionPassed() then
5374 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5375 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5376 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5377 address = if index then offset_addr else R[n];
5378 R[t] = ZeroExtend(MemU[address,1],32);
5379 if wback then R[n] = offset_addr;
5380#endif
5381
5382 bool success = false;
5383 const uint32_t opcode = OpcodeAsUnsigned (&success);
5384 if (!success)
5385 return false;
5386
5387 if (ConditionPassed ())
5388 {
5389 uint32_t t;
5390 uint32_t n;
5391 uint32_t m;
5392 bool index;
5393 bool add;
5394 bool wback;
5395 ARM_ShifterType shift_t;
5396 uint32_t shift_n;
5397
5398 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5399 switch (encoding)
5400 {
5401 case eEncodingT1:
5402 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5403 t = Bits32 (opcode, 2, 0);
5404 n = Bits32 (opcode, 5, 3);
5405 m = Bits32 (opcode, 8, 6);
5406
5407 // index = TRUE; add = TRUE; wback = FALSE;
5408 index = true;
5409 add = true;
5410 wback = false;
5411
5412 // (shift_t, shift_n) = (SRType_LSL, 0);
5413 shift_t = SRType_LSL;
5414 shift_n = 0;
5415 break;
5416
5417 case eEncodingT2:
5418 // if Rt == ’1111’ then SEE PLD;
5419 // if Rn == ’1111’ then SEE LDRB (literal);
5420 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5421 t = Bits32 (opcode, 15, 12);
5422 n = Bits32 (opcode, 19, 16);
5423 m = Bits32 (opcode, 3, 0);
5424
5425 // index = TRUE; add = TRUE; wback = FALSE;
5426 index = true;
5427 add = true;
5428 wback = false;
5429
5430 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5431 shift_t = SRType_LSL;
5432 shift_n = Bits32 (opcode, 5, 4);
5433
5434 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5435 if ((t == 13) || BadReg (m))
5436 return false;
5437 break;
5438
5439 case eEncodingA1:
5440 {
5441 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5442 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5443 t = Bits32 (opcode, 15, 12);
5444 n = Bits32 (opcode, 19, 16);
5445 m = Bits32 (opcode, 3, 0);
5446
5447 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5448 index = BitIsSet (opcode, 24);
5449 add = BitIsSet (opcode, 23);
5450 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5451
5452 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5453 uint32_t type = Bits32 (opcode, 6, 5);
5454 uint32_t imm5 = Bits32 (opcode, 11, 7);
5455 shift_n = DecodeImmShift (type, imm5, shift_t);
5456
5457 // if t == 15 || m == 15 then UNPREDICTABLE;
5458 if ((t == 15) || (m == 15))
5459 return false;
5460
5461 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5462 if (wback && ((n == 15) || (n == t)))
5463 return false;
5464 }
5465 break;
5466
5467 default:
5468 return false;
5469 }
5470
5471 addr_t offset_addr;
5472 addr_t address;
5473
5474 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5475 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5476 if (!success)
5477 return false;
5478
5479 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5480
5481 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5482 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5483 if (!success)
5484 return false;
5485
5486 if (add)
5487 offset_addr = Rn + offset;
5488 else
5489 offset_addr = Rn - offset;
5490
5491 // address = if index then offset_addr else R[n];
5492 if (index)
5493 address = offset_addr;
5494 else
5495 address = Rn;
5496
5497 // R[t] = ZeroExtend(MemU[address,1],32);
5498 Register base_reg;
5499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5500
5501 EmulateInstruction::Context context;
5502 context.type = eContextRegisterLoad;
5503 context.SetRegisterPlusOffset (base_reg, address - Rn);
5504
5505 uint64_t data = MemURead (context, address, 1, 0, &success);
5506 if (!success)
5507 return false;
5508
5509 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5510 return false;
5511
5512 // if wback then R[n] = offset_addr;
5513 if (wback)
5514 {
5515 context.type = eContextAdjustBaseRegister;
5516 context.SetAddress (offset_addr);
5517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5518 return false;
5519 }
5520 }
5521 return true;
5522}
Caroline Ticefe479112011-02-18 18:52:37 +00005523
Johnny Chen2115b412011-02-21 23:42:44 +00005524// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5525// and writes the result to the destination register. It can optionally update the condition flags based on
5526// the result.
5527bool
5528EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5529{
5530#if 0
5531 // ARM pseudo code...
5532 if ConditionPassed() then
5533 EncodingSpecificOperations();
5534 result = R[n] EOR imm32;
5535 if d == 15 then // Can only occur for ARM encoding
5536 ALUWritePC(result); // setflags is always FALSE here
5537 else
5538 R[d] = result;
5539 if setflags then
5540 APSR.N = result<31>;
5541 APSR.Z = IsZeroBit(result);
5542 APSR.C = carry;
5543 // APSR.V unchanged
5544#endif
5545
5546 bool success = false;
5547 const uint32_t opcode = OpcodeAsUnsigned (&success);
5548 if (!success)
5549 return false;
5550
5551 if (ConditionPassed())
5552 {
5553 uint32_t Rd, Rn;
5554 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5555 bool setflags;
5556 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5557 switch (encoding)
5558 {
5559 case eEncodingT1:
5560 Rd = Bits32(opcode, 11, 8);
5561 Rn = Bits32(opcode, 19, 16);
5562 setflags = BitIsSet(opcode, 20);
5563 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5564 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5565 if (Rd == 15 && setflags)
5566 return EmulateTEQImm(eEncodingT1);
5567 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5568 return false;
5569 break;
5570 case eEncodingA1:
5571 Rd = Bits32(opcode, 15, 12);
5572 Rn = Bits32(opcode, 19, 16);
5573 setflags = BitIsSet(opcode, 20);
5574 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5575 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5576 // TODO: Emulate SUBS PC, LR and related instructions.
5577 if (Rd == 15 && setflags)
5578 return false;
5579 break;
5580 default:
5581 return false;
5582 }
5583
5584 // Read the first operand.
5585 uint32_t val1 = ReadCoreReg(Rn, &success);
5586 if (!success)
5587 return false;
5588
5589 uint32_t result = val1 ^ imm32;
5590
5591 EmulateInstruction::Context context;
5592 context.type = EmulateInstruction::eContextImmediate;
5593 context.SetNoArgs ();
5594
5595 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5596 return false;
5597 }
5598 return true;
5599}
5600
5601// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5602// optionally-shifted register value, and writes the result to the destination register.
5603// It can optionally update the condition flags based on the result.
5604bool
5605EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5606{
5607#if 0
5608 // ARM pseudo code...
5609 if ConditionPassed() then
5610 EncodingSpecificOperations();
5611 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5612 result = R[n] EOR shifted;
5613 if d == 15 then // Can only occur for ARM encoding
5614 ALUWritePC(result); // setflags is always FALSE here
5615 else
5616 R[d] = result;
5617 if setflags then
5618 APSR.N = result<31>;
5619 APSR.Z = IsZeroBit(result);
5620 APSR.C = carry;
5621 // APSR.V unchanged
5622#endif
5623
5624 bool success = false;
5625 const uint32_t opcode = OpcodeAsUnsigned (&success);
5626 if (!success)
5627 return false;
5628
5629 if (ConditionPassed())
5630 {
5631 uint32_t Rd, Rn, Rm;
5632 ARM_ShifterType shift_t;
5633 uint32_t shift_n; // the shift applied to the value read from Rm
5634 bool setflags;
5635 uint32_t carry;
5636 switch (encoding)
5637 {
5638 case eEncodingT1:
5639 Rd = Rn = Bits32(opcode, 2, 0);
5640 Rm = Bits32(opcode, 5, 3);
5641 setflags = !InITBlock();
5642 shift_t = SRType_LSL;
5643 shift_n = 0;
5644 case eEncodingT2:
5645 Rd = Bits32(opcode, 11, 8);
5646 Rn = Bits32(opcode, 19, 16);
5647 Rm = Bits32(opcode, 3, 0);
5648 setflags = BitIsSet(opcode, 20);
5649 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5650 // if Rd == ‘1111’ && S == ‘1’ then SEE TEQ (register);
5651 if (Rd == 15 && setflags)
5652 return EmulateTEQReg(eEncodingT1);
5653 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5654 return false;
5655 break;
5656 case eEncodingA1:
5657 Rd = Bits32(opcode, 15, 12);
5658 Rn = Bits32(opcode, 19, 16);
5659 Rm = Bits32(opcode, 3, 0);
5660 setflags = BitIsSet(opcode, 20);
5661 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5662 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5663 // TODO: Emulate SUBS PC, LR and related instructions.
5664 if (Rd == 15 && setflags)
5665 return false;
5666 break;
5667 default:
5668 return false;
5669 }
5670
5671 // Read the first operand.
5672 uint32_t val1 = ReadCoreReg(Rn, &success);
5673 if (!success)
5674 return false;
5675
5676 // Read the second operand.
5677 uint32_t val2 = ReadCoreReg(Rm, &success);
5678 if (!success)
5679 return false;
5680
5681 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5682 uint32_t result = val1 ^ shifted;
5683
5684 EmulateInstruction::Context context;
5685 context.type = EmulateInstruction::eContextImmediate;
5686 context.SetNoArgs ();
5687
5688 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5689 return false;
5690 }
5691 return true;
5692}
5693
Johnny Chen7c5234d2011-02-18 23:41:11 +00005694// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5695// writes the result to the destination register. It can optionally update the condition flags based
5696// on the result.
5697bool
5698EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5699{
5700#if 0
5701 // ARM pseudo code...
5702 if ConditionPassed() then
5703 EncodingSpecificOperations();
5704 result = R[n] OR imm32;
5705 if d == 15 then // Can only occur for ARM encoding
5706 ALUWritePC(result); // setflags is always FALSE here
5707 else
5708 R[d] = result;
5709 if setflags then
5710 APSR.N = result<31>;
5711 APSR.Z = IsZeroBit(result);
5712 APSR.C = carry;
5713 // APSR.V unchanged
5714#endif
5715
5716 bool success = false;
5717 const uint32_t opcode = OpcodeAsUnsigned (&success);
5718 if (!success)
5719 return false;
5720
5721 if (ConditionPassed())
5722 {
5723 uint32_t Rd, Rn;
5724 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5725 bool setflags;
5726 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5727 switch (encoding)
5728 {
5729 case eEncodingT1:
5730 Rd = Bits32(opcode, 11, 8);
5731 Rn = Bits32(opcode, 19, 16);
5732 setflags = BitIsSet(opcode, 20);
5733 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5734 // if Rn == ‘1111’ then SEE MOV (immediate);
5735 if (Rn == 15)
5736 return EmulateMOVRdImm(eEncodingT2);
5737 if (BadReg(Rd) || Rn == 13)
5738 return false;
5739 break;
5740 case eEncodingA1:
5741 Rd = Bits32(opcode, 15, 12);
5742 Rn = Bits32(opcode, 19, 16);
5743 setflags = BitIsSet(opcode, 20);
5744 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5745 // TODO: Emulate SUBS PC, LR and related instructions.
5746 if (Rd == 15 && setflags)
5747 return false;
5748 break;
5749 default:
5750 return false;
5751 }
5752
5753 // Read the first operand.
5754 uint32_t val1 = ReadCoreReg(Rn, &success);
5755 if (!success)
5756 return false;
5757
5758 uint32_t result = val1 | imm32;
5759
5760 EmulateInstruction::Context context;
5761 context.type = EmulateInstruction::eContextImmediate;
5762 context.SetNoArgs ();
5763
5764 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5765 return false;
5766 }
5767 return true;
5768}
5769
5770// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5771// value, and writes the result to the destination register. It can optionally update the condition flags based
5772// on the result.
5773bool
5774EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5775{
5776#if 0
5777 // ARM pseudo code...
5778 if ConditionPassed() then
5779 EncodingSpecificOperations();
5780 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5781 result = R[n] OR shifted;
5782 if d == 15 then // Can only occur for ARM encoding
5783 ALUWritePC(result); // setflags is always FALSE here
5784 else
5785 R[d] = result;
5786 if setflags then
5787 APSR.N = result<31>;
5788 APSR.Z = IsZeroBit(result);
5789 APSR.C = carry;
5790 // APSR.V unchanged
5791#endif
5792
5793 bool success = false;
5794 const uint32_t opcode = OpcodeAsUnsigned (&success);
5795 if (!success)
5796 return false;
5797
5798 if (ConditionPassed())
5799 {
5800 uint32_t Rd, Rn, Rm;
5801 ARM_ShifterType shift_t;
5802 uint32_t shift_n; // the shift applied to the value read from Rm
5803 bool setflags;
5804 uint32_t carry;
5805 switch (encoding)
5806 {
5807 case eEncodingT1:
5808 Rd = Rn = Bits32(opcode, 2, 0);
5809 Rm = Bits32(opcode, 5, 3);
5810 setflags = !InITBlock();
5811 shift_t = SRType_LSL;
5812 shift_n = 0;
5813 case eEncodingT2:
5814 Rd = Bits32(opcode, 11, 8);
5815 Rn = Bits32(opcode, 19, 16);
5816 Rm = Bits32(opcode, 3, 0);
5817 setflags = BitIsSet(opcode, 20);
5818 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5819 // if Rn == ‘1111’ then SEE MOV (register);
5820 if (Rn == 15)
5821 return EmulateMOVRdRm(eEncodingT3);
5822 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5823 return false;
5824 break;
5825 case eEncodingA1:
5826 Rd = Bits32(opcode, 15, 12);
5827 Rn = Bits32(opcode, 19, 16);
5828 Rm = Bits32(opcode, 3, 0);
5829 setflags = BitIsSet(opcode, 20);
5830 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5831 // TODO: Emulate SUBS PC, LR and related instructions.
5832 if (Rd == 15 && setflags)
5833 return false;
5834 break;
5835 default:
5836 return false;
5837 }
5838
5839 // Read the first operand.
5840 uint32_t val1 = ReadCoreReg(Rn, &success);
5841 if (!success)
5842 return false;
5843
5844 // Read the second operand.
5845 uint32_t val2 = ReadCoreReg(Rm, &success);
5846 if (!success)
5847 return false;
5848
5849 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005850 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005851
5852 EmulateInstruction::Context context;
5853 context.type = EmulateInstruction::eContextImmediate;
5854 context.SetNoArgs ();
5855
5856 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5857 return false;
5858 }
5859 return true;
5860}
5861
Johnny Chen2115b412011-02-21 23:42:44 +00005862// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
5863// immediate value. It updates the condition flags based on the result, and discards the result.
5864bool
5865EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
5866{
5867#if 0
5868 // ARM pseudo code...
5869 if ConditionPassed() then
5870 EncodingSpecificOperations();
5871 result = R[n] EOR imm32;
5872 APSR.N = result<31>;
5873 APSR.Z = IsZeroBit(result);
5874 APSR.C = carry;
5875 // APSR.V unchanged
5876#endif
5877
5878 bool success = false;
5879 const uint32_t opcode = OpcodeAsUnsigned (&success);
5880 if (!success)
5881 return false;
5882
5883 if (ConditionPassed())
5884 {
5885 uint32_t Rn;
5886 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5887 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5888 switch (encoding)
5889 {
5890 case eEncodingT1:
5891 Rn = Bits32(opcode, 19, 16);
5892 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5893 if (BadReg(Rn))
5894 return false;
5895 break;
5896 case eEncodingA1:
5897 Rn = Bits32(opcode, 19, 16);
5898 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5899 break;
5900 default:
5901 return false;
5902 }
5903
5904 // Read the first operand.
5905 uint32_t val1 = ReadCoreReg(Rn, &success);
5906 if (!success)
5907 return false;
5908
5909 uint32_t result = val1 ^ imm32;
5910
5911 EmulateInstruction::Context context;
5912 context.type = EmulateInstruction::eContextImmediate;
5913 context.SetNoArgs ();
5914
5915 if (!WriteFlags(context, result, carry))
5916 return false;
5917 }
5918 return true;
5919}
5920
5921// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
5922// optionally-shifted register value. It updates the condition flags based on the result, and discards
5923// the result.
5924bool
5925EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
5926{
5927#if 0
5928 // ARM pseudo code...
5929 if ConditionPassed() then
5930 EncodingSpecificOperations();
5931 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5932 result = R[n] EOR shifted;
5933 APSR.N = result<31>;
5934 APSR.Z = IsZeroBit(result);
5935 APSR.C = carry;
5936 // APSR.V unchanged
5937#endif
5938
5939 bool success = false;
5940 const uint32_t opcode = OpcodeAsUnsigned (&success);
5941 if (!success)
5942 return false;
5943
5944 if (ConditionPassed())
5945 {
5946 uint32_t Rn, Rm;
5947 ARM_ShifterType shift_t;
5948 uint32_t shift_n; // the shift applied to the value read from Rm
5949 uint32_t carry;
5950 switch (encoding)
5951 {
5952 case eEncodingT1:
5953 Rn = Bits32(opcode, 19, 16);
5954 Rm = Bits32(opcode, 3, 0);
5955 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5956 if (BadReg(Rn) || BadReg(Rm))
5957 return false;
5958 break;
5959 case eEncodingA1:
5960 Rn = Bits32(opcode, 19, 16);
5961 Rm = Bits32(opcode, 3, 0);
5962 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5963 break;
5964 default:
5965 return false;
5966 }
5967
5968 // Read the first operand.
5969 uint32_t val1 = ReadCoreReg(Rn, &success);
5970 if (!success)
5971 return false;
5972
5973 // Read the second operand.
5974 uint32_t val2 = ReadCoreReg(Rm, &success);
5975 if (!success)
5976 return false;
5977
5978 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5979 uint32_t result = val1 ^ shifted;
5980
5981 EmulateInstruction::Context context;
5982 context.type = EmulateInstruction::eContextImmediate;
5983 context.SetNoArgs ();
5984
5985 if (!WriteFlags(context, result, carry))
5986 return false;
5987 }
5988 return true;
5989}
5990
Johnny Chende3cce32011-02-21 21:24:49 +00005991// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
5992// It updates the condition flags based on the result, and discards the result.
5993bool
5994EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
5995{
5996#if 0
5997 // ARM pseudo code...
5998 if ConditionPassed() then
5999 EncodingSpecificOperations();
6000 result = R[n] AND imm32;
6001 APSR.N = result<31>;
6002 APSR.Z = IsZeroBit(result);
6003 APSR.C = carry;
6004 // APSR.V unchanged
6005#endif
6006
6007 bool success = false;
6008 const uint32_t opcode = OpcodeAsUnsigned (&success);
6009 if (!success)
6010 return false;
6011
6012 if (ConditionPassed())
6013 {
6014 uint32_t Rn;
6015 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6016 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6017 switch (encoding)
6018 {
6019 case eEncodingT1:
6020 Rn = Bits32(opcode, 19, 16);
6021 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6022 if (BadReg(Rn))
6023 return false;
6024 break;
6025 case eEncodingA1:
6026 Rn = Bits32(opcode, 19, 16);
6027 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
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 (!WriteFlags(context, result, carry))
6045 return false;
6046 }
6047 return true;
6048}
6049
6050// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6051// It updates the condition flags based on the result, and discards the result.
6052bool
6053EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6054{
6055#if 0
6056 // ARM pseudo code...
6057 if ConditionPassed() then
6058 EncodingSpecificOperations();
6059 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6060 result = R[n] AND shifted;
6061 APSR.N = result<31>;
6062 APSR.Z = IsZeroBit(result);
6063 APSR.C = carry;
6064 // APSR.V unchanged
6065#endif
6066
6067 bool success = false;
6068 const uint32_t opcode = OpcodeAsUnsigned (&success);
6069 if (!success)
6070 return false;
6071
6072 if (ConditionPassed())
6073 {
6074 uint32_t Rn, Rm;
6075 ARM_ShifterType shift_t;
6076 uint32_t shift_n; // the shift applied to the value read from Rm
6077 uint32_t carry;
6078 switch (encoding)
6079 {
6080 case eEncodingT1:
6081 Rn = Bits32(opcode, 2, 0);
6082 Rm = Bits32(opcode, 5, 3);
6083 shift_t = SRType_LSL;
6084 shift_n = 0;
6085 case eEncodingT2:
6086 Rn = Bits32(opcode, 19, 16);
6087 Rm = Bits32(opcode, 3, 0);
6088 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
6089 if (BadReg(Rn) || BadReg(Rm))
6090 return false;
6091 break;
6092 case eEncodingA1:
6093 Rn = Bits32(opcode, 19, 16);
6094 Rm = Bits32(opcode, 3, 0);
6095 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
6096 break;
6097 default:
6098 return false;
6099 }
6100
6101 // Read the first operand.
6102 uint32_t val1 = ReadCoreReg(Rn, &success);
6103 if (!success)
6104 return false;
6105
6106 // Read the second operand.
6107 uint32_t val2 = ReadCoreReg(Rm, &success);
6108 if (!success)
6109 return false;
6110
6111 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6112 uint32_t result = val1 & shifted;
6113
6114 EmulateInstruction::Context context;
6115 context.type = EmulateInstruction::eContextImmediate;
6116 context.SetNoArgs ();
6117
6118 if (!WriteFlags(context, result, carry))
6119 return false;
6120 }
6121 return true;
6122}
6123
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006124EmulateInstructionARM::ARMOpcode*
6125EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006126{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006127 static ARMOpcode
6128 g_arm_opcodes[] =
6129 {
6130 //----------------------------------------------------------------------
6131 // Prologue instructions
6132 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006133
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006134 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006135 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6136 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006137
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006138 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006139 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006140 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006141 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006142 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6143 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006144 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006145
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006146 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006147 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006148
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006149 // push one register
6150 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006151 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006152
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006153 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006154 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6155 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006156
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006157 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006158 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006159 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006160
Johnny Chen9f687722011-02-18 00:02:28 +00006161 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6162 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006163 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006164 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6165
6166 //----------------------------------------------------------------------
6167 // Supervisor Call (previously Software Interrupt)
6168 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006169 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6170
6171 //----------------------------------------------------------------------
6172 // Branch instructions
6173 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006174 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006175 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6176 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6177 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6178 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006179 // for example, "bx lr"
6180 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006181
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006182 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006183 // Data-processing instructions
6184 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006185 // adc (immediate)
6186 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6187 // adc (register)
6188 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006189 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006190 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006191 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006192 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006193 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006194 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006195 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006196 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006197 // eor (immediate)
6198 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6199 // eor (register)
6200 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006201 // orr (immediate)
6202 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6203 // orr (register)
6204 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006205 // teq (immediate)
6206 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6207 // teq (register)
6208 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006209 // tst (immediate)
6210 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6211 // tst (register)
6212 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6213
6214
Johnny Chend642a6a2011-02-22 01:01:03 +00006215 // mvn (immediate)
6216 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6217 // mvn (register)
6218 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006219 // cmn (immediate)
6220 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6221 // cmn (register)
6222 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006223 // cmp (immediate)
6224 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6225 // cmp (register)
6226 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006227 // asr (immediate)
6228 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006229 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006230 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006231 // lsl (immediate)
6232 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6233 // lsl (register)
6234 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6235 // lsr (immediate)
6236 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6237 // lsr (register)
6238 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006239 // rrx is a special case encoding of ror (immediate)
6240 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6241 // ror (immediate)
6242 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6243 // ror (register)
6244 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006245
6246 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006247 // Load instructions
6248 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006249 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006250 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006251 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006252 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006253 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006254 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00006255 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
6256 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00006257
6258 //----------------------------------------------------------------------
6259 // Store instructions
6260 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00006261 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006262 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00006263 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00006264 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
6265 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00006266
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006267
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006268 };
6269 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
6270
6271 for (size_t i=0; i<k_num_arm_opcodes; ++i)
6272 {
6273 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
6274 return &g_arm_opcodes[i];
6275 }
6276 return NULL;
6277}
Greg Clayton64c84432011-01-21 22:02:52 +00006278
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006279
6280EmulateInstructionARM::ARMOpcode*
6281EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00006282{
Johnny Chenfdd179e2011-01-31 20:09:28 +00006283
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006284 static ARMOpcode
6285 g_thumb_opcodes[] =
6286 {
6287 //----------------------------------------------------------------------
6288 // Prologue instructions
6289 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00006290
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006291 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006292 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6293 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
6294 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00006295
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006296 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006297 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006298 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00006299 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006300 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00006301 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00006302
Johnny Chen864a8e82011-02-18 00:07:39 +00006303 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00006304 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00006305
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006306 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006307 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
6308 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
6309 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
6310 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006311
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006312 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00006313 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6314 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006315
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006316 //----------------------------------------------------------------------
6317 // Epilogue instructions
6318 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00006319
Johnny Chen864a8e82011-02-18 00:07:39 +00006320 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00006321 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6322 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
6323 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00006324 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
6325 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006326
6327 //----------------------------------------------------------------------
6328 // Supervisor Call (previously Software Interrupt)
6329 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00006330 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
6331
6332 //----------------------------------------------------------------------
6333 // If Then makes up to four following instructions conditional.
6334 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006335 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
6336
6337 //----------------------------------------------------------------------
6338 // Branch instructions
6339 //----------------------------------------------------------------------
6340 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
6341 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
6342 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00006343 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006344 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00006345 // J1 == J2 == 1
6346 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6347 // J1 == J2 == 1
6348 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6349 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006350 // for example, "bx lr"
6351 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00006352 // compare and branch
6353 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00006354 // table branch byte
6355 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
6356 // table branch halfword
6357 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006358
6359 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00006360 // Data-processing instructions
6361 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006362 // adc (immediate)
6363 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
6364 // adc (register)
6365 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
6366 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
6367 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00006368 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006369 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00006370 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006371 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006372 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006373 // and (register)
6374 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
6375 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006376 // eor (immediate)
6377 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
6378 // eor (register)
6379 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
6380 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006381 // orr (immediate)
6382 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
6383 // orr (register)
6384 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
6385 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006386 // teq (immediate)
6387 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
6388 // teq (register)
6389 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006390 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00006391 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00006392 // tst (register)
6393 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
6394 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
6395
Johnny Chen7c5234d2011-02-18 23:41:11 +00006396
Johnny Chen338bf542011-02-10 19:29:03 +00006397 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00006398 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00006399 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00006400 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006401 // mov{s}<c>.w <Rd>, <Rm>
6402 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00006403 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00006404 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
6405 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00006406 // mvn (immediate)
6407 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
6408 // mvn (register)
6409 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
6410 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006411 // cmn (immediate)
6412 { 0xfbf08f00, 0xf1100f00, ARMvAll, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6413 // cmn (register)
6414 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
6415 { 0xfff08f00, 0xeb100f00, ARMvAll, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
6416 // cmp (immediate)
6417 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
6418 // cmp (register) (Rn and Rm both from r0-r7)
6419 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
6420 // cmp (register) (Rn and Rm not both from r0-r7)
6421 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006422 // asr (immediate)
6423 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00006424 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00006425 // asr (register)
6426 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
6427 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006428 // lsl (immediate)
6429 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
6430 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
6431 // lsl (register)
6432 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
6433 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
6434 // lsr (immediate)
6435 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
6436 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
6437 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00006438 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006439 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006440 // rrx is a special case encoding of ror (immediate)
6441 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
6442 // ror (immediate)
6443 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
6444 // ror (register)
6445 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
6446 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006447
6448 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006449 // Load instructions
6450 //----------------------------------------------------------------------
6451 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00006452 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00006453 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00006454 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
6455 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00006456 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00006457 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
6458 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00006459 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
6460 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
6461 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00006462 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00006463 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
6464 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00006465
6466 //----------------------------------------------------------------------
6467 // Store instructions
6468 //----------------------------------------------------------------------
6469 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006470 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00006471 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00006472 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
6473 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
6474 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
6475 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
6476 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
6477 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
6478 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
6479 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
6480 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006481 };
6482
6483 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
6484 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
6485 {
6486 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
6487 return &g_thumb_opcodes[i];
6488 }
6489 return NULL;
6490}
Greg Clayton64c84432011-01-21 22:02:52 +00006491
Greg Clayton31e2a382011-01-30 20:03:56 +00006492bool
Greg Clayton395fc332011-02-15 21:59:32 +00006493EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00006494{
6495 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00006496 const char *arch_cstr = arch.AsCString ();
6497 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00006498 {
Greg Clayton395fc332011-02-15 21:59:32 +00006499 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
6500 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
6501 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
6502 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
6503 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
6504 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
6505 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
6506 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
6507 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
6508 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00006509 }
6510 return m_arm_isa != 0;
6511}
6512
6513
Greg Clayton64c84432011-01-21 22:02:52 +00006514bool
6515EmulateInstructionARM::ReadInstruction ()
6516{
6517 bool success = false;
6518 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
6519 if (success)
6520 {
6521 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
6522 if (success)
6523 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00006524 Context read_inst_context;
6525 read_inst_context.type = eContextReadOpcode;
6526 read_inst_context.SetNoArgs ();
6527
Greg Clayton64c84432011-01-21 22:02:52 +00006528 if (m_inst_cpsr & MASK_CPSR_T)
6529 {
6530 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006531 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006532
6533 if (success)
6534 {
6535 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
6536 {
6537 m_inst.opcode_type = eOpcode16;
6538 m_inst.opcode.inst16 = thumb_opcode;
6539 }
6540 else
6541 {
6542 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006543 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006544 }
6545 }
6546 }
6547 else
6548 {
6549 m_inst_mode = eModeARM;
6550 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006551 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006552 }
6553 }
6554 }
6555 if (!success)
6556 {
6557 m_inst_mode = eModeInvalid;
6558 m_inst_pc = LLDB_INVALID_ADDRESS;
6559 }
6560 return success;
6561}
6562
Johnny Chenee9b1f72011-02-09 01:00:31 +00006563uint32_t
6564EmulateInstructionARM::ArchVersion ()
6565{
6566 return m_arm_isa;
6567}
6568
Greg Clayton64c84432011-01-21 22:02:52 +00006569bool
6570EmulateInstructionARM::ConditionPassed ()
6571{
6572 if (m_inst_cpsr == 0)
6573 return false;
6574
6575 const uint32_t cond = CurrentCond ();
6576
6577 if (cond == UINT32_MAX)
6578 return false;
6579
6580 bool result = false;
6581 switch (UnsignedBits(cond, 3, 1))
6582 {
6583 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
6584 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
6585 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
6586 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
6587 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
6588 case 5:
6589 {
6590 bool n = (m_inst_cpsr & MASK_CPSR_N);
6591 bool v = (m_inst_cpsr & MASK_CPSR_V);
6592 result = n == v;
6593 }
6594 break;
6595 case 6:
6596 {
6597 bool n = (m_inst_cpsr & MASK_CPSR_N);
6598 bool v = (m_inst_cpsr & MASK_CPSR_V);
6599 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
6600 }
6601 break;
6602 case 7:
6603 result = true;
6604 break;
6605 }
6606
6607 if (cond & 1)
6608 result = !result;
6609 return result;
6610}
6611
Johnny Chen9ee056b2011-02-08 00:06:35 +00006612uint32_t
6613EmulateInstructionARM::CurrentCond ()
6614{
6615 switch (m_inst_mode)
6616 {
6617 default:
6618 case eModeInvalid:
6619 break;
6620
6621 case eModeARM:
6622 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
6623
6624 case eModeThumb:
6625 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
6626 // 'cond' field of the encoding.
6627 if (m_inst.opcode_type == eOpcode16 &&
6628 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
6629 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
6630 {
6631 return Bits32(m_inst.opcode.inst16, 11, 7);
6632 }
6633 else if (m_inst.opcode_type == eOpcode32 &&
6634 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
6635 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
6636 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
6637 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
6638 {
6639 return Bits32(m_inst.opcode.inst32, 25, 22);
6640 }
6641
6642 return m_it_session.GetCond();
6643 }
6644 return UINT32_MAX; // Return invalid value
6645}
6646
Johnny Chen9ee056b2011-02-08 00:06:35 +00006647bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00006648EmulateInstructionARM::InITBlock()
6649{
6650 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
6651}
6652
6653bool
6654EmulateInstructionARM::LastInITBlock()
6655{
6656 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
6657}
6658
6659bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00006660EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
6661{
6662 addr_t target;
6663
Johnny Chenee9b1f72011-02-09 01:00:31 +00006664 // Check the current instruction set.
6665 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006666 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006667 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00006668 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006669
Johnny Chen9ee056b2011-02-08 00:06:35 +00006670 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006671 return false;
6672
6673 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006674}
6675
6676// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
6677bool
Johnny Chen668b4512011-02-15 21:08:58 +00006678EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006679{
6680 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00006681 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
6682 // we want to record it and issue a WriteRegister callback so the clients
6683 // can track the mode changes accordingly.
6684 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006685
6686 if (BitIsSet(addr, 0))
6687 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006688 if (CurrentInstrSet() != eModeThumb)
6689 {
6690 SelectInstrSet(eModeThumb);
6691 cpsr_changed = true;
6692 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006693 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00006694 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006695 }
6696 else if (BitIsClear(addr, 1))
6697 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006698 if (CurrentInstrSet() != eModeARM)
6699 {
6700 SelectInstrSet(eModeARM);
6701 cpsr_changed = true;
6702 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006703 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00006704 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006705 }
6706 else
6707 return false; // address<1:0> == '10' => UNPREDICTABLE
6708
Johnny Chen0f309db2011-02-09 19:11:32 +00006709 if (cpsr_changed)
6710 {
Johnny Chen558133b2011-02-09 23:59:17 +00006711 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00006712 return false;
6713 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006714 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006715 return false;
6716
6717 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006718}
Greg Clayton64c84432011-01-21 22:02:52 +00006719
Johnny Chenee9b1f72011-02-09 01:00:31 +00006720// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
6721bool
Johnny Chen668b4512011-02-15 21:08:58 +00006722EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00006723{
6724 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00006725 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00006726 else
6727 return BranchWritePC((const Context)context, addr);
6728}
6729
Johnny Chen26863dc2011-02-09 23:43:29 +00006730// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
6731bool
Johnny Chen668b4512011-02-15 21:08:58 +00006732EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00006733{
6734 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00006735 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00006736 else
6737 return BranchWritePC((const Context)context, addr);
6738}
6739
Johnny Chenee9b1f72011-02-09 01:00:31 +00006740EmulateInstructionARM::Mode
6741EmulateInstructionARM::CurrentInstrSet ()
6742{
6743 return m_inst_mode;
6744}
6745
6746// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00006747// ReadInstruction() is performed. This function has a side effect of updating
6748// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00006749bool
6750EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
6751{
Johnny Chen558133b2011-02-09 23:59:17 +00006752 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006753 switch (arm_or_thumb)
6754 {
6755 default:
6756 return false;
6757 eModeARM:
6758 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006759 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006760 break;
6761 eModeThumb:
6762 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006763 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006764 break;
6765 }
6766 return true;
6767}
6768
Johnny Chenef21b592011-02-10 01:52:38 +00006769// This function returns TRUE if the processor currently provides support for
6770// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
6771// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
6772bool
6773EmulateInstructionARM::UnalignedSupport()
6774{
6775 return (ArchVersion() >= ARMv7);
6776}
6777
Johnny Chenbf6ad172011-02-11 01:29:53 +00006778// The main addition and subtraction instructions can produce status information
6779// about both unsigned carry and signed overflow conditions. This status
6780// information can be used to synthesize multi-word additions and subtractions.
6781EmulateInstructionARM::AddWithCarryResult
6782EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
6783{
6784 uint32_t result;
6785 uint8_t carry_out;
6786 uint8_t overflow;
6787
6788 uint64_t unsigned_sum = x + y + carry_in;
6789 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
6790
6791 result = UnsignedBits(unsigned_sum, 31, 0);
6792 carry_out = (result == unsigned_sum ? 0 : 1);
6793 overflow = ((int32_t)result == signed_sum ? 0 : 1);
6794
6795 AddWithCarryResult res = { result, carry_out, overflow };
6796 return res;
6797}
6798
Johnny Chen157b9592011-02-18 21:13:05 +00006799uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00006800EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00006801{
Johnny Chene39f22d2011-02-19 01:36:13 +00006802 uint32_t reg_kind, reg_num;
6803 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00006804 {
Johnny Chene39f22d2011-02-19 01:36:13 +00006805 case SP_REG:
6806 reg_kind = eRegisterKindGeneric;
6807 reg_num = LLDB_REGNUM_GENERIC_SP;
6808 break;
6809 case LR_REG:
6810 reg_kind = eRegisterKindGeneric;
6811 reg_num = LLDB_REGNUM_GENERIC_RA;
6812 break;
6813 case PC_REG:
6814 reg_kind = eRegisterKindGeneric;
6815 reg_num = LLDB_REGNUM_GENERIC_PC;
6816 break;
6817 default:
6818 if (0 <= num && num < SP_REG)
6819 {
6820 reg_kind = eRegisterKindDWARF;
6821 reg_num = dwarf_r0 + num;
6822 }
Johnny Chen157b9592011-02-18 21:13:05 +00006823 else
Johnny Chene39f22d2011-02-19 01:36:13 +00006824 {
6825 assert(0 && "Invalid register number");
6826 *success = false;
6827 return ~0u;
6828 }
6829 break;
Johnny Chen157b9592011-02-18 21:13:05 +00006830 }
Johnny Chene39f22d2011-02-19 01:36:13 +00006831
6832 // Read our register.
6833 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
6834
6835 // When executing an ARM instruction , PC reads as the address of the current
6836 // instruction plus 8.
6837 // When executing a Thumb instruction , PC reads as the address of the current
6838 // instruction plus 4.
6839 if (num == 15)
6840 {
6841 if (CurrentInstrSet() == eModeARM)
6842 val += 8;
6843 else
6844 val += 4;
6845 }
Johnny Chen157b9592011-02-18 21:13:05 +00006846
6847 return val;
6848}
6849
Johnny Chenca67d1c2011-02-17 01:35:27 +00006850// Write the result to the ARM core register Rd, and optionally update the
6851// condition flags based on the result.
6852//
6853// This helper method tries to encapsulate the following pseudocode from the
6854// ARM Architecture Reference Manual:
6855//
6856// if d == 15 then // Can only occur for encoding A1
6857// ALUWritePC(result); // setflags is always FALSE here
6858// else
6859// R[d] = result;
6860// if setflags then
6861// APSR.N = result<31>;
6862// APSR.Z = IsZeroBit(result);
6863// APSR.C = carry;
6864// // APSR.V unchanged
6865//
6866// In the above case, the API client does not pass in the overflow arg, which
6867// defaults to ~0u.
6868bool
Johnny Chen10530c22011-02-17 22:37:12 +00006869EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
6870 const uint32_t result,
6871 const uint32_t Rd,
6872 bool setflags,
6873 const uint32_t carry,
6874 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00006875{
6876 if (Rd == 15)
6877 {
6878 if (!ALUWritePC (context, result))
6879 return false;
6880 }
6881 else
6882 {
6883 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
6884 return false;
6885 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00006886 return WriteFlags (context, result, carry, overflow);
6887 }
6888 return true;
6889}
6890
6891// This helper method tries to encapsulate the following pseudocode from the
6892// ARM Architecture Reference Manual:
6893//
6894// APSR.N = result<31>;
6895// APSR.Z = IsZeroBit(result);
6896// APSR.C = carry;
6897// APSR.V = overflow
6898//
6899// Default arguments can be specified for carry and overflow parameters, which means
6900// not to update the respective flags.
6901bool
6902EmulateInstructionARM::WriteFlags (Context &context,
6903 const uint32_t result,
6904 const uint32_t carry,
6905 const uint32_t overflow)
6906{
6907 m_new_inst_cpsr = m_inst_cpsr;
6908 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
6909 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
6910 if (carry != ~0u)
6911 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
6912 if (overflow != ~0u)
6913 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
6914 if (m_new_inst_cpsr != m_inst_cpsr)
6915 {
6916 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
6917 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00006918 }
6919 return true;
6920}
6921
Greg Clayton64c84432011-01-21 22:02:52 +00006922bool
6923EmulateInstructionARM::EvaluateInstruction ()
6924{
Johnny Chenc315f862011-02-05 00:46:10 +00006925 // Advance the ITSTATE bits to their values for the next instruction.
6926 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
6927 m_it_session.ITAdvance();
6928
Greg Clayton64c84432011-01-21 22:02:52 +00006929 return false;
6930}