blob: 6ad2c8990053272ecad52750cb261a7f5d5d9d71 [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 Chen28070c32011-02-12 01:27:26 +0000717// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
718// the destination register. It can optionally update the condition flags based
719// on the value.
720// MVN (immediate)
721bool
Johnny Chen9f687722011-02-18 00:02:28 +0000722EmulateInstructionARM::EmulateMVNRdImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000723{
724#if 0
725 // ARM pseudo code...
726 if (ConditionPassed())
727 {
728 EncodingSpecificOperations();
729 result = NOT(imm32);
730 if d == 15 then // Can only occur for ARM encoding
731 ALUWritePC(result); // setflags is always FALSE here
732 else
733 R[d] = result;
734 if setflags then
735 APSR.N = result<31>;
736 APSR.Z = IsZeroBit(result);
737 APSR.C = carry;
738 // APSR.V unchanged
739 }
740#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000741 bool success = false;
742 const uint32_t opcode = OpcodeAsUnsigned (&success);
743 if (!success)
744 return false;
745
746 if (ConditionPassed())
747 {
748 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000749 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
750 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
751 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000752 bool setflags;
753 switch (encoding) {
754 case eEncodingT1:
755 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000756 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000757 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000758 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000759 break;
760 case eEncodingA1:
761 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000762 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000763 imm12 = Bits32(opcode, 11, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000764 imm32 = ARMExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000765 break;
766 default:
767 return false;
768 }
769 uint32_t result = ~imm32;
770
771 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000772 EmulateInstruction::Context context;
773 context.type = EmulateInstruction::eContextImmediate;
774 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000775
Johnny Chen10530c22011-02-17 22:37:12 +0000776 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000777 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000778 }
779 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000780}
781
Johnny Chen788e0552011-01-27 22:52:23 +0000782// PC relative immediate load into register, possibly followed by ADD (SP plus register).
783// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000784bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000785EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000786{
787#if 0
788 // ARM pseudo code...
789 if (ConditionPassed())
790 {
791 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
792 base = Align(PC,4);
793 address = if add then (base + imm32) else (base - imm32);
794 data = MemU[address,4];
795 if t == 15 then
796 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
797 elsif UnalignedSupport() || address<1:0> = ‘00’ then
798 R[t] = data;
799 else // Can only apply before ARMv7
800 if CurrentInstrSet() == InstrSet_ARM then
801 R[t] = ROR(data, 8*UInt(address<1:0>));
802 else
803 R[t] = bits(32) UNKNOWN;
804 }
805#endif
806
807 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000808 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000809 if (!success)
810 return false;
811
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000812 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000813 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000814 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000815 if (!success)
816 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000817
818 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000819 EmulateInstruction::Context context;
820 context.type = EmulateInstruction::eContextRegisterPlusOffset;
821 Register pc_reg;
822 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
823 context.SetRegisterPlusOffset (pc_reg, 0);
824
Johnny Chenc9de9102011-02-11 19:12:30 +0000825 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000826 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000827 bool add; // +imm32 or -imm32?
828 addr_t base; // the base address
829 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000830 uint32_t data; // the literal data value from the PC relative load
831 switch (encoding) {
832 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000833 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000834 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000835 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000836 break;
837 case eEncodingT2:
838 Rt = Bits32(opcode, 15, 12);
839 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
840 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000841 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000842 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000843 break;
844 default:
845 return false;
846 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000847
Johnny Chene39f22d2011-02-19 01:36:13 +0000848 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000849 if (add)
850 address = base + imm32;
851 else
852 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000853
854 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000855 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000856 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000857 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000858
859 if (Rt == 15)
860 {
861 if (Bits32(address, 1, 0) == 0)
862 {
863 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000864 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000865 return false;
866 }
867 else
868 return false;
869 }
870 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
871 {
872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
873 return false;
874 }
875 else // We don't handle ARM for now.
876 return false;
877
878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000879 return false;
880 }
881 return true;
882}
883
Johnny Chen5b442b72011-01-27 19:34:30 +0000884// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000885// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000886bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000887EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000888{
889#if 0
890 // ARM pseudo code...
891 if (ConditionPassed())
892 {
893 EncodingSpecificOperations();
894 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
895 if d == 15 then // Can only occur for ARM encoding
896 ALUWritePC(result); // setflags is always FALSE here
897 else
898 R[d] = result;
899 if setflags then
900 APSR.N = result<31>;
901 APSR.Z = IsZeroBit(result);
902 APSR.C = carry;
903 APSR.V = overflow;
904 }
905#endif
906
907 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000908 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000909 if (!success)
910 return false;
911
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000912 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000913 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000914 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000915 if (!success)
916 return false;
917 uint32_t imm32; // the immediate operand
918 switch (encoding) {
919 case eEncodingT2:
920 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
921 break;
922 default:
923 return false;
924 }
925 addr_t sp_offset = imm32;
926 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
927
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000928 EmulateInstruction::Context context;
929 context.type = EmulateInstruction::eContextAdjustStackPointer;
930 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000931
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000932 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000933 return false;
934 }
935 return true;
936}
937
938// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000939// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000940bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000941EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000942{
943#if 0
944 // ARM pseudo code...
945 if (ConditionPassed())
946 {
947 EncodingSpecificOperations();
948 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
949 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
950 if d == 15 then
951 ALUWritePC(result); // setflags is always FALSE here
952 else
953 R[d] = result;
954 if setflags then
955 APSR.N = result<31>;
956 APSR.Z = IsZeroBit(result);
957 APSR.C = carry;
958 APSR.V = overflow;
959 }
960#endif
961
962 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000963 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000964 if (!success)
965 return false;
966
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000967 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000968 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000969 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000970 if (!success)
971 return false;
972 uint32_t Rm; // the second operand
973 switch (encoding) {
974 case eEncodingT2:
975 Rm = Bits32(opcode, 6, 3);
976 break;
977 default:
978 return false;
979 }
Johnny Chene39f22d2011-02-19 01:36:13 +0000980 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000981 if (!success)
982 return false;
983
984 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
985
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000986 EmulateInstruction::Context context;
987 context.type = EmulateInstruction::eContextAdjustStackPointer;
988 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000989
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000990 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000991 return false;
992 }
993 return true;
994}
995
Johnny Chen9b8d7832011-02-02 01:13:56 +0000996// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
997// at a PC-relative address, and changes instruction set from ARM to Thumb, or
998// from Thumb to ARM.
999// BLX (immediate)
1000bool
1001EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1002{
1003#if 0
1004 // ARM pseudo code...
1005 if (ConditionPassed())
1006 {
1007 EncodingSpecificOperations();
1008 if CurrentInstrSet() == InstrSet_ARM then
1009 LR = PC - 4;
1010 else
1011 LR = PC<31:1> : '1';
1012 if targetInstrSet == InstrSet_ARM then
1013 targetAddress = Align(PC,4) + imm32;
1014 else
1015 targetAddress = PC + imm32;
1016 SelectInstrSet(targetInstrSet);
1017 BranchWritePC(targetAddress);
1018 }
1019#endif
1020
1021 bool success = false;
1022 const uint32_t opcode = OpcodeAsUnsigned (&success);
1023 if (!success)
1024 return false;
1025
1026 if (ConditionPassed())
1027 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001028 EmulateInstruction::Context context;
1029 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001030 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001031 if (!success)
1032 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001033 addr_t lr; // next instruction address
1034 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001035 int32_t imm32; // PC-relative offset
1036 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001037 case eEncodingT1:
1038 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001039 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001040 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001041 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001042 uint32_t J1 = Bit32(opcode, 13);
1043 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001044 uint32_t imm11 = Bits32(opcode, 10, 0);
1045 uint32_t I1 = !(J1 ^ S);
1046 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001047 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001048 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001049 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001050 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001051 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001052 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001053 break;
1054 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001055 case eEncodingT2:
1056 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001057 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001058 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001059 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001060 uint32_t J1 = Bit32(opcode, 13);
1061 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001062 uint32_t imm10L = Bits32(opcode, 10, 1);
1063 uint32_t I1 = !(J1 ^ S);
1064 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001065 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001066 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001067 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001068 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001069 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001070 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001071 break;
1072 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001073 case eEncodingA1:
1074 lr = pc + 4; // return address
1075 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001076 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001077 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001078 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001079 case eEncodingA2:
1080 lr = pc + 4; // return address
1081 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001082 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001083 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001084 break;
1085 default:
1086 return false;
1087 }
1088 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1089 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001090 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001091 return false;
1092 }
1093 return true;
1094}
1095
1096// Branch with Link and Exchange (register) calls a subroutine at an address and
1097// instruction set specified by a register.
1098// BLX (register)
1099bool
1100EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1101{
1102#if 0
1103 // ARM pseudo code...
1104 if (ConditionPassed())
1105 {
1106 EncodingSpecificOperations();
1107 target = R[m];
1108 if CurrentInstrSet() == InstrSet_ARM then
1109 next_instr_addr = PC - 4;
1110 LR = next_instr_addr;
1111 else
1112 next_instr_addr = PC - 2;
1113 LR = next_instr_addr<31:1> : ‘1’;
1114 BXWritePC(target);
1115 }
1116#endif
1117
1118 bool success = false;
1119 const uint32_t opcode = OpcodeAsUnsigned (&success);
1120 if (!success)
1121 return false;
1122
1123 if (ConditionPassed())
1124 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001125 EmulateInstruction::Context context;
1126 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001127 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001128 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001129 if (!success)
1130 return false;
1131 uint32_t Rm; // the register with the target address
1132 switch (encoding) {
1133 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001134 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001135 Rm = Bits32(opcode, 6, 3);
1136 // if m == 15 then UNPREDICTABLE;
1137 if (Rm == 15)
1138 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001139 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001140 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001141 break;
1142 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001143 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001144 Rm = Bits32(opcode, 3, 0);
1145 // if m == 15 then UNPREDICTABLE;
1146 if (Rm == 15)
1147 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001148 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001149 default:
1150 return false;
1151 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001152 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001153 if (!success)
1154 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001155 Register dwarf_reg;
1156 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1157 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001158 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1159 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001160 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001161 return false;
1162 }
1163 return true;
1164}
1165
Johnny Chenab3b3512011-02-12 00:10:51 +00001166// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1167// BX
1168bool
1169EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1170{
1171#if 0
1172 // ARM pseudo code...
1173 if (ConditionPassed())
1174 {
1175 EncodingSpecificOperations();
1176 BXWritePC(R[m]);
1177 }
1178#endif
1179
1180 bool success = false;
1181 const uint32_t opcode = OpcodeAsUnsigned (&success);
1182 if (!success)
1183 return false;
1184
1185 if (ConditionPassed())
1186 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001187 EmulateInstruction::Context context;
1188 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001189 uint32_t Rm; // the register with the target address
1190 switch (encoding) {
1191 case eEncodingT1:
1192 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001193 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001194 return false;
1195 break;
1196 case eEncodingA1:
1197 Rm = Bits32(opcode, 3, 0);
1198 break;
1199 default:
1200 return false;
1201 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001202 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001203 if (!success)
1204 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001205
1206 Register dwarf_reg;
1207 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001208 context.SetRegister (dwarf_reg);
1209 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001210 return false;
1211 }
1212 return true;
1213}
1214
Johnny Chen0d0148e2011-01-28 02:26:08 +00001215// Set r7 to point to some ip offset.
1216// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001218EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001219{
1220#if 0
1221 // ARM pseudo code...
1222 if (ConditionPassed())
1223 {
1224 EncodingSpecificOperations();
1225 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1226 if d == 15 then // Can only occur for ARM encoding
1227 ALUWritePC(result); // setflags is always FALSE here
1228 else
1229 R[d] = result;
1230 if setflags then
1231 APSR.N = result<31>;
1232 APSR.Z = IsZeroBit(result);
1233 APSR.C = carry;
1234 APSR.V = overflow;
1235 }
1236#endif
1237
1238 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001239 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001240 if (!success)
1241 return false;
1242
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001243 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001244 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001245 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001246 if (!success)
1247 return false;
1248 uint32_t imm32;
1249 switch (encoding) {
1250 case eEncodingA1:
1251 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1252 break;
1253 default:
1254 return false;
1255 }
1256 addr_t ip_offset = imm32;
1257 addr_t addr = ip - ip_offset; // the adjusted ip value
1258
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001259 EmulateInstruction::Context context;
1260 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1261 Register dwarf_reg;
1262 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1263 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001264
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001265 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001266 return false;
1267 }
1268 return true;
1269}
1270
1271// Set ip to point to some stack offset.
1272// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001273bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001274EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001275{
1276#if 0
1277 // ARM pseudo code...
1278 if (ConditionPassed())
1279 {
1280 EncodingSpecificOperations();
1281 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1282 if d == 15 then // Can only occur for ARM encoding
1283 ALUWritePC(result); // setflags is always FALSE here
1284 else
1285 R[d] = result;
1286 if setflags then
1287 APSR.N = result<31>;
1288 APSR.Z = IsZeroBit(result);
1289 APSR.C = carry;
1290 APSR.V = overflow;
1291 }
1292#endif
1293
1294 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001295 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001296 if (!success)
1297 return false;
1298
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001299 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001300 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001301 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001302 if (!success)
1303 return false;
1304 uint32_t imm32;
1305 switch (encoding) {
1306 case eEncodingA1:
1307 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1308 break;
1309 default:
1310 return false;
1311 }
1312 addr_t sp_offset = imm32;
1313 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1314
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001315 EmulateInstruction::Context context;
1316 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1317 Register dwarf_reg;
1318 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1319 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001320
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001322 return false;
1323 }
1324 return true;
1325}
1326
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001327// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001328bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001329EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001330{
1331#if 0
1332 // ARM pseudo code...
1333 if (ConditionPassed())
1334 {
1335 EncodingSpecificOperations();
1336 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1337 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001338 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001339 else
1340 R[d] = result;
1341 if setflags then
1342 APSR.N = result<31>;
1343 APSR.Z = IsZeroBit(result);
1344 APSR.C = carry;
1345 APSR.V = overflow;
1346 }
1347#endif
1348
1349 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001350 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001351 if (!success)
1352 return false;
1353
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001354 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001355 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001356 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001357 if (!success)
1358 return false;
1359 uint32_t imm32;
1360 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001361 case eEncodingT1:
1362 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001363 case eEncodingT2:
1364 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1365 break;
1366 case eEncodingT3:
1367 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1368 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001369 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001370 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001371 break;
1372 default:
1373 return false;
1374 }
1375 addr_t sp_offset = imm32;
1376 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1377
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001378 EmulateInstruction::Context context;
1379 context.type = EmulateInstruction::eContextAdjustStackPointer;
1380 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001381
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001382 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001383 return false;
1384 }
1385 return true;
1386}
1387
Johnny Chen08c25e82011-01-31 18:02:28 +00001388// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001389bool
1390EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001391{
1392#if 0
1393 // ARM pseudo code...
1394 if (ConditionPassed())
1395 {
1396 EncodingSpecificOperations();
1397 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1398 address = if index then offset_addr else R[n];
1399 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1400 if wback then R[n] = offset_addr;
1401 }
1402#endif
1403
1404 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001405 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001406 if (!success)
1407 return false;
1408
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001409 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001410 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001411 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001412 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001413 if (!success)
1414 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001415 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001416 uint32_t imm12;
1417 switch (encoding) {
1418 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001419 Rt = Bits32(opcode, 15, 12);
1420 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001421 break;
1422 default:
1423 return false;
1424 }
1425 addr_t sp_offset = imm12;
1426 addr_t addr = sp - sp_offset;
1427
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001428 EmulateInstruction::Context context;
1429 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1430 Register dwarf_reg;
1431 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001432 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001434 dwarf_reg.num = dwarf_r0 + Rt;
1435 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001436 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001437 if (!success)
1438 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001439 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001440 return false;
1441 }
1442 else
1443 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001444 dwarf_reg.num = dwarf_pc;
1445 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001446 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001447 if (!success)
1448 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001449 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001450 return false;
1451 }
1452
1453 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001454 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001455
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001456 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001457 return false;
1458 }
1459 return true;
1460}
1461
Johnny Chen08c25e82011-01-31 18:02:28 +00001462// Vector Push stores multiple extension registers to the stack.
1463// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001464bool
1465EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001466{
1467#if 0
1468 // ARM pseudo code...
1469 if (ConditionPassed())
1470 {
1471 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1472 address = SP - imm32;
1473 SP = SP - imm32;
1474 if single_regs then
1475 for r = 0 to regs-1
1476 MemA[address,4] = S[d+r]; address = address+4;
1477 else
1478 for r = 0 to regs-1
1479 // Store as two word-aligned words in the correct order for current endianness.
1480 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1481 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1482 address = address+8;
1483 }
1484#endif
1485
1486 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001487 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001488 if (!success)
1489 return false;
1490
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001491 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001492 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001493 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001494 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001495 if (!success)
1496 return false;
1497 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001498 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001499 uint32_t imm32; // stack offset
1500 uint32_t regs; // number of registers
1501 switch (encoding) {
1502 case eEncodingT1:
1503 case eEncodingA1:
1504 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001505 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001506 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1507 // If UInt(imm8) is odd, see "FSTMX".
1508 regs = Bits32(opcode, 7, 0) / 2;
1509 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1510 if (regs == 0 || regs > 16 || (d + regs) > 32)
1511 return false;
1512 break;
1513 case eEncodingT2:
1514 case eEncodingA2:
1515 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001516 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001517 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1518 regs = Bits32(opcode, 7, 0);
1519 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1520 if (regs == 0 || regs > 16 || (d + regs) > 32)
1521 return false;
1522 break;
1523 default:
1524 return false;
1525 }
1526 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1527 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1528 addr_t sp_offset = imm32;
1529 addr_t addr = sp - sp_offset;
1530 uint32_t i;
1531
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001532 EmulateInstruction::Context context;
1533 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1534 Register dwarf_reg;
1535 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001536 for (i=d; i<regs; ++i)
1537 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001538 dwarf_reg.num = start_reg + i;
1539 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001540 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001541 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001542 if (!success)
1543 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001544 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001545 return false;
1546 addr += reg_byte_size;
1547 }
1548
1549 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001550 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001551
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001552 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001553 return false;
1554 }
1555 return true;
1556}
1557
Johnny Chen587a0a42011-02-01 18:35:28 +00001558// Vector Pop loads multiple extension registers from the stack.
1559// It also updates SP to point just above the loaded data.
1560bool
1561EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1562{
1563#if 0
1564 // ARM pseudo code...
1565 if (ConditionPassed())
1566 {
1567 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1568 address = SP;
1569 SP = SP + imm32;
1570 if single_regs then
1571 for r = 0 to regs-1
1572 S[d+r] = MemA[address,4]; address = address+4;
1573 else
1574 for r = 0 to regs-1
1575 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1576 // Combine the word-aligned words in the correct order for current endianness.
1577 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1578 }
1579#endif
1580
1581 bool success = false;
1582 const uint32_t opcode = OpcodeAsUnsigned (&success);
1583 if (!success)
1584 return false;
1585
1586 if (ConditionPassed())
1587 {
1588 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001589 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001590 if (!success)
1591 return false;
1592 bool single_regs;
1593 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1594 uint32_t imm32; // stack offset
1595 uint32_t regs; // number of registers
1596 switch (encoding) {
1597 case eEncodingT1:
1598 case eEncodingA1:
1599 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001600 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001601 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1602 // If UInt(imm8) is odd, see "FLDMX".
1603 regs = Bits32(opcode, 7, 0) / 2;
1604 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1605 if (regs == 0 || regs > 16 || (d + regs) > 32)
1606 return false;
1607 break;
1608 case eEncodingT2:
1609 case eEncodingA2:
1610 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001611 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001612 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1613 regs = Bits32(opcode, 7, 0);
1614 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1615 if (regs == 0 || regs > 16 || (d + regs) > 32)
1616 return false;
1617 break;
1618 default:
1619 return false;
1620 }
1621 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1622 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1623 addr_t sp_offset = imm32;
1624 addr_t addr = sp;
1625 uint32_t i;
1626 uint64_t data; // uint64_t to accomodate 64-bit registers.
1627
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001628 EmulateInstruction::Context context;
1629 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1630 Register dwarf_reg;
1631 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001632 for (i=d; i<regs; ++i)
1633 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001634 dwarf_reg.num = start_reg + i;
1635 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001636 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001637 if (!success)
1638 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001639 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001640 return false;
1641 addr += reg_byte_size;
1642 }
1643
1644 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001645 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001646
1647 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1648 return false;
1649 }
1650 return true;
1651}
1652
Johnny Chenb77be412011-02-04 00:40:18 +00001653// SVC (previously SWI)
1654bool
1655EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1656{
1657#if 0
1658 // ARM pseudo code...
1659 if (ConditionPassed())
1660 {
1661 EncodingSpecificOperations();
1662 CallSupervisor();
1663 }
1664#endif
1665
1666 bool success = false;
1667 const uint32_t opcode = OpcodeAsUnsigned (&success);
1668 if (!success)
1669 return false;
1670
1671 if (ConditionPassed())
1672 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001673 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001674 addr_t lr; // next instruction address
1675 if (!success)
1676 return false;
1677 uint32_t imm32; // the immediate constant
1678 uint32_t mode; // ARM or Thumb mode
1679 switch (encoding) {
1680 case eEncodingT1:
1681 lr = (pc + 2) | 1u; // return address
1682 imm32 = Bits32(opcode, 7, 0);
1683 mode = eModeThumb;
1684 break;
1685 case eEncodingA1:
1686 lr = pc + 4; // return address
1687 imm32 = Bits32(opcode, 23, 0);
1688 mode = eModeARM;
1689 break;
1690 default:
1691 return false;
1692 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001693
1694 EmulateInstruction::Context context;
1695 context.type = EmulateInstruction::eContextSupervisorCall;
1696 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001697 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1698 return false;
1699 }
1700 return true;
1701}
1702
Johnny Chenc315f862011-02-05 00:46:10 +00001703// If Then makes up to four following instructions (the IT block) conditional.
1704bool
1705EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1706{
1707#if 0
1708 // ARM pseudo code...
1709 EncodingSpecificOperations();
1710 ITSTATE.IT<7:0> = firstcond:mask;
1711#endif
1712
1713 bool success = false;
1714 const uint32_t opcode = OpcodeAsUnsigned (&success);
1715 if (!success)
1716 return false;
1717
1718 m_it_session.InitIT(Bits32(opcode, 7, 0));
1719 return true;
1720}
1721
Johnny Chen3b620b32011-02-07 20:11:47 +00001722// Branch causes a branch to a target address.
1723bool
1724EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1725{
1726#if 0
1727 // ARM pseudo code...
1728 if (ConditionPassed())
1729 {
1730 EncodingSpecificOperations();
1731 BranchWritePC(PC + imm32);
1732 }
1733#endif
1734
1735 bool success = false;
1736 const uint32_t opcode = OpcodeAsUnsigned (&success);
1737 if (!success)
1738 return false;
1739
Johnny Chen9ee056b2011-02-08 00:06:35 +00001740 if (ConditionPassed())
1741 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001742 EmulateInstruction::Context context;
1743 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001744 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001745 if (!success)
1746 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001747 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001748 int32_t imm32; // PC-relative offset
1749 switch (encoding) {
1750 case eEncodingT1:
1751 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1752 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001753 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001754 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001755 break;
1756 case eEncodingT2:
1757 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001758 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001759 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001760 break;
1761 case eEncodingT3:
1762 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1763 {
Johnny Chenbd599902011-02-10 21:39:01 +00001764 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001765 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001766 uint32_t J1 = Bit32(opcode, 13);
1767 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001768 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001769 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001770 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001771 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001772 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001773 break;
1774 }
1775 case eEncodingT4:
1776 {
Johnny Chenbd599902011-02-10 21:39:01 +00001777 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001778 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001779 uint32_t J1 = Bit32(opcode, 13);
1780 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001781 uint32_t imm11 = Bits32(opcode, 10, 0);
1782 uint32_t I1 = !(J1 ^ S);
1783 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001784 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001785 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001786 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001787 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001788 break;
1789 }
1790 case eEncodingA1:
1791 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001792 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001793 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001794 break;
1795 default:
1796 return false;
1797 }
1798 if (!BranchWritePC(context, target))
1799 return false;
1800 }
1801 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001802}
1803
Johnny Chen53ebab72011-02-08 23:21:57 +00001804// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1805// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1806// CBNZ, CBZ
1807bool
1808EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1809{
1810#if 0
1811 // ARM pseudo code...
1812 EncodingSpecificOperations();
1813 if nonzero ^ IsZero(R[n]) then
1814 BranchWritePC(PC + imm32);
1815#endif
1816
1817 bool success = false;
1818 const uint32_t opcode = OpcodeAsUnsigned (&success);
1819 if (!success)
1820 return false;
1821
1822 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00001823 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001824 if (!success)
1825 return false;
1826
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001827 EmulateInstruction::Context context;
1828 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001829 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00001830 if (!success)
1831 return false;
1832
1833 addr_t target; // target address
1834 uint32_t imm32; // PC-relative offset to branch forward
1835 bool nonzero;
1836 switch (encoding) {
1837 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001838 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001839 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00001840 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001841 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001842 break;
1843 default:
1844 return false;
1845 }
1846 if (nonzero ^ (reg_val == 0))
1847 if (!BranchWritePC(context, target))
1848 return false;
1849
1850 return true;
1851}
1852
Johnny Chen60299ec2011-02-17 19:34:27 +00001853// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1854// A base register provides a pointer to the table, and a second register supplies an index into the table.
1855// The branch length is twice the value of the byte returned from the table.
1856//
1857// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1858// A base register provides a pointer to the table, and a second register supplies an index into the table.
1859// The branch length is twice the value of the halfword returned from the table.
1860// TBB, TBH
1861bool
1862EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1863{
1864#if 0
1865 // ARM pseudo code...
1866 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1867 if is_tbh then
1868 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1869 else
1870 halfwords = UInt(MemU[R[n]+R[m], 1]);
1871 BranchWritePC(PC + 2*halfwords);
1872#endif
1873
1874 bool success = false;
1875 const uint32_t opcode = OpcodeAsUnsigned (&success);
1876 if (!success)
1877 return false;
1878
1879 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1880 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1881 bool is_tbh; // true if table branch halfword
1882 switch (encoding) {
1883 case eEncodingT1:
1884 Rn = Bits32(opcode, 19, 16);
1885 Rm = Bits32(opcode, 3, 0);
1886 is_tbh = BitIsSet(opcode, 4);
1887 if (Rn == 13 || BadReg(Rm))
1888 return false;
1889 if (InITBlock() && !LastInITBlock())
1890 return false;
1891 break;
1892 default:
1893 return false;
1894 }
1895
1896 // Read the address of the table from the operand register Rn.
1897 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00001898 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001899 if (!success)
1900 return false;
1901
1902 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00001903 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001904 if (!success)
1905 return false;
1906
1907 // the offsetted table address
1908 addr_t addr = base + (is_tbh ? index*2 : index);
1909
1910 // PC-relative offset to branch forward
1911 EmulateInstruction::Context context;
1912 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001913 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001914 if (!success)
1915 return false;
1916
Johnny Chene39f22d2011-02-19 01:36:13 +00001917 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00001918 if (!success)
1919 return false;
1920
1921 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00001922 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00001923 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1924 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
1925
1926 if (!BranchWritePC(context, target))
1927 return false;
1928
1929 return true;
1930}
1931
Johnny Chen8fa20592011-02-18 01:22:22 +00001932// This instruction adds an immediate value to a register value, and writes the result to the destination
1933// register. It can optionally update the condition flags based on the result.
1934bool
1935EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
1936{
1937#if 0
1938 // ARM pseudo code...
1939 if ConditionPassed() then
1940 EncodingSpecificOperations();
1941 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1942 if d == 15 then
1943 ALUWritePC(result); // setflags is always FALSE here
1944 else
1945 R[d] = result;
1946 if setflags then
1947 APSR.N = result<31>;
1948 APSR.Z = IsZeroBit(result);
1949 APSR.C = carry;
1950 APSR.V = overflow;
1951#endif
1952
1953 bool success = false;
1954 const uint32_t opcode = OpcodeAsUnsigned (&success);
1955 if (!success)
1956 return false;
1957
1958 if (ConditionPassed())
1959 {
1960 uint32_t Rd, Rn;
1961 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
1962 bool setflags;
1963 switch (encoding)
1964 {
1965 case eEncodingA1:
1966 Rd = Bits32(opcode, 15, 12);
1967 Rn = Bits32(opcode, 19, 16);
1968 setflags = BitIsSet(opcode, 20);
1969 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1970 break;
1971 default:
1972 return false;
1973 }
1974
Johnny Chen8fa20592011-02-18 01:22:22 +00001975 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00001976 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00001977 if (!success)
1978 return false;
1979
1980 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1981
1982 EmulateInstruction::Context context;
1983 context.type = EmulateInstruction::eContextImmediate;
1984 context.SetNoArgs ();
1985
1986 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1987 return false;
1988 }
1989 return true;
1990}
1991
Johnny Chend761dcf2011-02-17 22:03:29 +00001992// This instruction adds a register value and an optionally-shifted register value, and writes the result
1993// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001994bool
Johnny Chen9f687722011-02-18 00:02:28 +00001995EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001996{
1997#if 0
1998 // ARM pseudo code...
1999 if ConditionPassed() then
2000 EncodingSpecificOperations();
2001 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2002 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2003 if d == 15 then
2004 ALUWritePC(result); // setflags is always FALSE here
2005 else
2006 R[d] = result;
2007 if setflags then
2008 APSR.N = result<31>;
2009 APSR.Z = IsZeroBit(result);
2010 APSR.C = carry;
2011 APSR.V = overflow;
2012#endif
2013
2014 bool success = false;
2015 const uint32_t opcode = OpcodeAsUnsigned (&success);
2016 if (!success)
2017 return false;
2018
2019 if (ConditionPassed())
2020 {
2021 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002022 ARM_ShifterType shift_t;
2023 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002024 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002025 switch (encoding)
2026 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002027 case eEncodingT1:
2028 Rd = Bits32(opcode, 2, 0);
2029 Rn = Bits32(opcode, 5, 3);
2030 Rm = Bits32(opcode, 8, 6);
2031 setflags = !InITBlock();
2032 shift_t = SRType_LSL;
2033 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002034 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002035 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002036 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002037 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002038 shift_t = SRType_LSL;
2039 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002040 if (Rn == 15 && Rm == 15)
2041 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002042 if (Rd == 15 && InITBlock() && !LastInITBlock())
2043 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002044 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002045 case eEncodingA1:
2046 Rd = Bits32(opcode, 15, 12);
2047 Rn = Bits32(opcode, 19, 16);
2048 Rm = Bits32(opcode, 3, 0);
2049 setflags = BitIsSet(opcode, 20);
2050 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2051 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002052 default:
2053 return false;
2054 }
2055
Johnny Chen26863dc2011-02-09 23:43:29 +00002056 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002057 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002058 if (!success)
2059 return false;
2060
2061 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002062 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002063 if (!success)
2064 return false;
2065
Johnny Chene97c0d52011-02-18 19:32:20 +00002066 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002067 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002068
2069 EmulateInstruction::Context context;
2070 context.type = EmulateInstruction::eContextImmediate;
2071 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002072
Johnny Chen10530c22011-02-17 22:37:12 +00002073 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002074 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002075 }
2076 return true;
2077}
2078
Johnny Chene4a4d302011-02-11 21:53:58 +00002079// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002080bool
Johnny Chen9f687722011-02-18 00:02:28 +00002081EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002082{
2083#if 0
2084 // ARM pseudo code...
2085 if ConditionPassed() then
2086 EncodingSpecificOperations();
2087 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2088 APSR.N = result<31>;
2089 APSR.Z = IsZeroBit(result);
2090 APSR.C = carry;
2091 APSR.V = overflow;
2092#endif
2093
2094 bool success = false;
2095 const uint32_t opcode = OpcodeAsUnsigned (&success);
2096 if (!success)
2097 return false;
2098
2099 uint32_t Rn; // the first operand
2100 uint32_t imm32; // the immediate value to be compared with
2101 switch (encoding) {
2102 case eEncodingT1:
2103 Rn = Bits32(opcode, 10, 8);
2104 imm32 = Bits32(opcode, 7, 0);
2105 break;
2106 default:
2107 return false;
2108 }
2109 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002110 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002111 if (!success)
2112 return false;
2113
Johnny Chen10530c22011-02-17 22:37:12 +00002114 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2115
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002116 EmulateInstruction::Context context;
2117 context.type = EmulateInstruction::eContextImmediate;
2118 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002119 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2120 return false;
2121
Johnny Chend4dc4442011-02-11 02:02:56 +00002122 return true;
2123}
2124
Johnny Chene4a4d302011-02-11 21:53:58 +00002125// CMP (register)
2126bool
Johnny Chen9f687722011-02-18 00:02:28 +00002127EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002128{
2129#if 0
2130 // ARM pseudo code...
2131 if ConditionPassed() then
2132 EncodingSpecificOperations();
2133 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2134 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2135 APSR.N = result<31>;
2136 APSR.Z = IsZeroBit(result);
2137 APSR.C = carry;
2138 APSR.V = overflow;
2139#endif
2140
2141 bool success = false;
2142 const uint32_t opcode = OpcodeAsUnsigned (&success);
2143 if (!success)
2144 return false;
2145
2146 uint32_t Rn; // the first operand
2147 uint32_t Rm; // the second operand
2148 switch (encoding) {
2149 case eEncodingT1:
2150 Rn = Bits32(opcode, 2, 0);
2151 Rm = Bits32(opcode, 5, 3);
2152 break;
2153 case eEncodingT2:
2154 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2155 Rm = Bits32(opcode, 6, 3);
2156 if (Rn < 8 && Rm < 8)
2157 return false;
2158 if (Rn == 15 || Rm == 15)
2159 return false;
2160 break;
2161 default:
2162 return false;
2163 }
2164 // Read the register value from register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002165 uint32_t reg_val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002166 if (!success)
2167 return false;
2168 // Read the register value from register Rm.
2169 // The register value is not being shifted since we don't handle ARM for now.
Johnny Chene39f22d2011-02-19 01:36:13 +00002170 uint32_t reg_val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002171 if (!success)
2172 return false;
2173
Johnny Chen10530c22011-02-17 22:37:12 +00002174 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2175
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002176 EmulateInstruction::Context context;
2177 context.type = EmulateInstruction::eContextImmediate;
2178 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002179 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2180 return false;
2181
Johnny Chene4a4d302011-02-11 21:53:58 +00002182 return true;
2183}
2184
Johnny Chen82f16aa2011-02-15 20:10:55 +00002185// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2186// shifting in copies of its sign bit, and writes the result to the destination register. It can
2187// optionally update the condition flags based on the result.
2188bool
2189EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2190{
2191#if 0
2192 // ARM pseudo code...
2193 if ConditionPassed() then
2194 EncodingSpecificOperations();
2195 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2196 if d == 15 then // Can only occur for ARM encoding
2197 ALUWritePC(result); // setflags is always FALSE here
2198 else
2199 R[d] = result;
2200 if setflags then
2201 APSR.N = result<31>;
2202 APSR.Z = IsZeroBit(result);
2203 APSR.C = carry;
2204 // APSR.V unchanged
2205#endif
2206
Johnny Chen41a0a152011-02-16 01:27:54 +00002207 return EmulateShiftImm(encoding, SRType_ASR);
2208}
2209
2210// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2211// shifting in copies of its sign bit, and writes the result to the destination register.
2212// The variable number of bits is read from the bottom byte of a register. It can optionally update
2213// the condition flags based on the result.
2214bool
2215EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2216{
2217#if 0
2218 // ARM pseudo code...
2219 if ConditionPassed() then
2220 EncodingSpecificOperations();
2221 shift_n = UInt(R[m]<7:0>);
2222 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2223 R[d] = result;
2224 if setflags then
2225 APSR.N = result<31>;
2226 APSR.Z = IsZeroBit(result);
2227 APSR.C = carry;
2228 // APSR.V unchanged
2229#endif
2230
2231 return EmulateShiftReg(encoding, SRType_ASR);
2232}
2233
2234// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2235// shifting in zeros, and writes the result to the destination register. It can optionally
2236// update the condition flags based on the result.
2237bool
2238EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2239{
2240#if 0
2241 // ARM pseudo code...
2242 if ConditionPassed() then
2243 EncodingSpecificOperations();
2244 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2245 if d == 15 then // Can only occur for ARM encoding
2246 ALUWritePC(result); // setflags is always FALSE here
2247 else
2248 R[d] = result;
2249 if setflags then
2250 APSR.N = result<31>;
2251 APSR.Z = IsZeroBit(result);
2252 APSR.C = carry;
2253 // APSR.V unchanged
2254#endif
2255
2256 return EmulateShiftImm(encoding, SRType_LSL);
2257}
2258
2259// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2260// shifting in zeros, and writes the result to the destination register. The variable number
2261// of bits is read from the bottom byte of a register. It can optionally update the condition
2262// flags based on the result.
2263bool
2264EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2265{
2266#if 0
2267 // ARM pseudo code...
2268 if ConditionPassed() then
2269 EncodingSpecificOperations();
2270 shift_n = UInt(R[m]<7:0>);
2271 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2272 R[d] = result;
2273 if setflags then
2274 APSR.N = result<31>;
2275 APSR.Z = IsZeroBit(result);
2276 APSR.C = carry;
2277 // APSR.V unchanged
2278#endif
2279
2280 return EmulateShiftReg(encoding, SRType_LSL);
2281}
2282
2283// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2284// shifting in zeros, and writes the result to the destination register. It can optionally
2285// update the condition flags based on the result.
2286bool
2287EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2288{
2289#if 0
2290 // ARM pseudo code...
2291 if ConditionPassed() then
2292 EncodingSpecificOperations();
2293 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2294 if d == 15 then // Can only occur for ARM encoding
2295 ALUWritePC(result); // setflags is always FALSE here
2296 else
2297 R[d] = result;
2298 if setflags then
2299 APSR.N = result<31>;
2300 APSR.Z = IsZeroBit(result);
2301 APSR.C = carry;
2302 // APSR.V unchanged
2303#endif
2304
2305 return EmulateShiftImm(encoding, SRType_LSR);
2306}
2307
2308// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2309// shifting in zeros, and writes the result to the destination register. The variable number
2310// of bits is read from the bottom byte of a register. It can optionally update the condition
2311// flags based on the result.
2312bool
2313EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2314{
2315#if 0
2316 // ARM pseudo code...
2317 if ConditionPassed() then
2318 EncodingSpecificOperations();
2319 shift_n = UInt(R[m]<7:0>);
2320 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2321 R[d] = result;
2322 if setflags then
2323 APSR.N = result<31>;
2324 APSR.Z = IsZeroBit(result);
2325 APSR.C = carry;
2326 // APSR.V unchanged
2327#endif
2328
2329 return EmulateShiftReg(encoding, SRType_LSR);
2330}
2331
Johnny Cheneeab4852011-02-16 22:14:44 +00002332// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2333// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2334// It can optionally update the condition flags based on the result.
2335bool
2336EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2337{
2338#if 0
2339 // ARM pseudo code...
2340 if ConditionPassed() then
2341 EncodingSpecificOperations();
2342 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2343 if d == 15 then // Can only occur for ARM encoding
2344 ALUWritePC(result); // setflags is always FALSE here
2345 else
2346 R[d] = result;
2347 if setflags then
2348 APSR.N = result<31>;
2349 APSR.Z = IsZeroBit(result);
2350 APSR.C = carry;
2351 // APSR.V unchanged
2352#endif
2353
2354 return EmulateShiftImm(encoding, SRType_ROR);
2355}
2356
2357// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2358// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2359// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2360// flags based on the result.
2361bool
2362EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2363{
2364#if 0
2365 // ARM pseudo code...
2366 if ConditionPassed() then
2367 EncodingSpecificOperations();
2368 shift_n = UInt(R[m]<7:0>);
2369 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2370 R[d] = result;
2371 if setflags then
2372 APSR.N = result<31>;
2373 APSR.Z = IsZeroBit(result);
2374 APSR.C = carry;
2375 // APSR.V unchanged
2376#endif
2377
2378 return EmulateShiftReg(encoding, SRType_ROR);
2379}
2380
2381// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2382// with the carry flag shifted into bit [31].
2383//
2384// RRX can optionally update the condition flags based on the result.
2385// In that case, bit [0] is shifted into the carry flag.
2386bool
2387EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2388{
2389#if 0
2390 // ARM pseudo code...
2391 if ConditionPassed() then
2392 EncodingSpecificOperations();
2393 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2394 if d == 15 then // Can only occur for ARM encoding
2395 ALUWritePC(result); // setflags is always FALSE here
2396 else
2397 R[d] = result;
2398 if setflags then
2399 APSR.N = result<31>;
2400 APSR.Z = IsZeroBit(result);
2401 APSR.C = carry;
2402 // APSR.V unchanged
2403#endif
2404
2405 return EmulateShiftImm(encoding, SRType_RRX);
2406}
2407
Johnny Chen41a0a152011-02-16 01:27:54 +00002408bool
2409EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2410{
2411 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2412
Johnny Chen82f16aa2011-02-15 20:10:55 +00002413 bool success = false;
2414 const uint32_t opcode = OpcodeAsUnsigned (&success);
2415 if (!success)
2416 return false;
2417
2418 if (ConditionPassed())
2419 {
Johnny Chene7f89532011-02-15 23:22:46 +00002420 uint32_t Rd; // the destination register
2421 uint32_t Rm; // the first operand register
2422 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002423 uint32_t carry; // the carry bit after the shift operation
2424 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002425
2426 // Special case handling!
2427 // A8.6.139 ROR (immediate) -- Encoding T1
2428 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2429 {
2430 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2431 // have the same decoding of bit fields as the other Thumb2 shift operations.
2432 encoding = eEncodingT2;
2433 }
2434
Johnny Chen82f16aa2011-02-15 20:10:55 +00002435 switch (encoding) {
2436 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002437 // Due to the above special case handling!
2438 assert(shift_type != SRType_ROR);
2439
Johnny Chen82f16aa2011-02-15 20:10:55 +00002440 Rd = Bits32(opcode, 2, 0);
2441 Rm = Bits32(opcode, 5, 3);
2442 setflags = !InITBlock();
2443 imm5 = Bits32(opcode, 10, 6);
2444 break;
2445 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002446 // A8.6.141 RRX
2447 assert(shift_type != SRType_RRX);
2448
Johnny Chen82f16aa2011-02-15 20:10:55 +00002449 Rd = Bits32(opcode, 11, 8);
2450 Rm = Bits32(opcode, 3, 0);
2451 setflags = BitIsSet(opcode, 20);
2452 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2453 if (BadReg(Rd) || BadReg(Rm))
2454 return false;
2455 break;
2456 case eEncodingA1:
2457 Rd = Bits32(opcode, 15, 12);
2458 Rm = Bits32(opcode, 3, 0);
2459 setflags = BitIsSet(opcode, 20);
2460 imm5 = Bits32(opcode, 11, 7);
2461 break;
2462 default:
2463 return false;
2464 }
2465
Johnny Cheneeab4852011-02-16 22:14:44 +00002466 // A8.6.139 ROR (immediate)
2467 if (shift_type == SRType_ROR && imm5 == 0)
2468 shift_type = SRType_RRX;
2469
Johnny Chen82f16aa2011-02-15 20:10:55 +00002470 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002471 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002472 if (!success)
2473 return false;
2474
Johnny Cheneeab4852011-02-16 22:14:44 +00002475 // Decode the shift amount if not RRX.
2476 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002477
Johnny Chene97c0d52011-02-18 19:32:20 +00002478 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002479
2480 // The context specifies that an immediate is to be moved into Rd.
2481 EmulateInstruction::Context context;
2482 context.type = EmulateInstruction::eContextImmediate;
2483 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002484
Johnny Chen10530c22011-02-17 22:37:12 +00002485 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002486 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002487 }
2488 return true;
2489}
2490
Johnny Chene7f89532011-02-15 23:22:46 +00002491bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002492EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002493{
Johnny Chen41a0a152011-02-16 01:27:54 +00002494 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002495
2496 bool success = false;
2497 const uint32_t opcode = OpcodeAsUnsigned (&success);
2498 if (!success)
2499 return false;
2500
2501 if (ConditionPassed())
2502 {
2503 uint32_t Rd; // the destination register
2504 uint32_t Rn; // the first operand register
2505 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2506 uint32_t carry; // the carry bit after the shift operation
2507 bool setflags;
2508 switch (encoding) {
2509 case eEncodingT1:
2510 Rd = Bits32(opcode, 2, 0);
2511 Rn = Rd;
2512 Rm = Bits32(opcode, 5, 3);
2513 setflags = !InITBlock();
2514 break;
2515 case eEncodingT2:
2516 Rd = Bits32(opcode, 11, 8);
2517 Rn = Bits32(opcode, 19, 16);
2518 Rm = Bits32(opcode, 3, 0);
2519 setflags = BitIsSet(opcode, 20);
2520 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2521 return false;
2522 break;
2523 case eEncodingA1:
2524 Rd = Bits32(opcode, 15, 12);
2525 Rn = Bits32(opcode, 3, 0);
2526 Rm = Bits32(opcode, 11, 8);
2527 setflags = BitIsSet(opcode, 20);
2528 if (Rd == 15 || Rn == 15 || Rm == 15)
2529 return false;
2530 break;
2531 default:
2532 return false;
2533 }
2534
2535 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002536 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002537 if (!success)
2538 return false;
2539 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002540 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002541 if (!success)
2542 return false;
2543
2544 // Get the shift amount.
2545 uint32_t amt = Bits32(val, 7, 0);
2546
Johnny Chene97c0d52011-02-18 19:32:20 +00002547 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002548
2549 // The context specifies that an immediate is to be moved into Rd.
2550 EmulateInstruction::Context context;
2551 context.type = EmulateInstruction::eContextImmediate;
2552 context.SetNoArgs ();
2553
Johnny Chen10530c22011-02-17 22:37:12 +00002554 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002555 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002556 }
2557 return true;
2558}
2559
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002560// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002561// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002562// can be written back to the base register.
2563bool
2564EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2565{
2566#if 0
2567 // ARM pseudo code...
2568 if ConditionPassed()
2569 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2570 address = R[n];
2571
2572 for i = 0 to 14
2573 if registers<i> == '1' then
2574 R[i] = MemA[address, 4]; address = address + 4;
2575 if registers<15> == '1' then
2576 LoadWritePC (MemA[address, 4]);
2577
2578 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2579 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2580
2581#endif
2582
2583 bool success = false;
2584 const uint32_t opcode = OpcodeAsUnsigned (&success);
2585 if (!success)
2586 return false;
2587
2588 if (ConditionPassed())
2589 {
2590 uint32_t n;
2591 uint32_t registers = 0;
2592 bool wback;
2593 const uint32_t addr_byte_size = GetAddressByteSize();
2594 switch (encoding)
2595 {
2596 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002597 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002598 n = Bits32 (opcode, 10, 8);
2599 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002600 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002601 wback = BitIsClear (registers, n);
2602 // if BitCount(registers) < 1 then UNPREDICTABLE;
2603 if (BitCount(registers) < 1)
2604 return false;
2605 break;
2606 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002607 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2608 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002609 n = Bits32 (opcode, 19, 16);
2610 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002611 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002612 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002613
2614 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002615 if ((n == 15)
2616 || (BitCount (registers) < 2)
2617 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2618 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002619
2620 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002621 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002622 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002623
2624 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002625 if (wback
2626 && BitIsSet (registers, n))
2627 return false;
2628 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002629
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002630 case eEncodingA1:
2631 n = Bits32 (opcode, 19, 16);
2632 registers = Bits32 (opcode, 15, 0);
2633 wback = BitIsSet (opcode, 21);
2634 if ((n == 15)
2635 || (BitCount (registers) < 1))
2636 return false;
2637 break;
2638 default:
2639 return false;
2640 }
2641
2642 int32_t offset = 0;
2643 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2644 if (!success)
2645 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002646
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002647 EmulateInstruction::Context context;
2648 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2649 Register dwarf_reg;
2650 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2651 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002652
2653 for (int i = 0; i < 14; ++i)
2654 {
2655 if (BitIsSet (registers, i))
2656 {
Caroline Tice85aab332011-02-08 23:56:10 +00002657 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002658 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002659 if (wback && (n == 13)) // Pop Instruction
2660 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2661
2662 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002663 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002664 if (!success)
2665 return false;
2666
2667 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2668 return false;
2669
2670 offset += addr_byte_size;
2671 }
2672 }
2673
2674 if (BitIsSet (registers, 15))
2675 {
2676 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002677 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002678 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002679 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002680 if (!success)
2681 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002682 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002683 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002684 return false;
2685 }
2686
2687 if (wback && BitIsClear (registers, n))
2688 {
Caroline Ticefa172202011-02-11 22:49:54 +00002689 // R[n] = R[n] + 4 * BitCount (registers)
2690 int32_t offset = addr_byte_size * BitCount (registers);
2691 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002692 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002693
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2695 return false;
2696 }
2697 if (wback && BitIsSet (registers, n))
2698 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002699 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002700 }
2701 return true;
2702}
Caroline Tice713c2662011-02-11 17:59:55 +00002703
2704// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2705// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2706// can optionally be written back tot he base registers.
2707bool
2708EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2709{
2710#if 0
2711 // ARM pseudo code...
2712 if ConditionPassed() then
2713 EncodingSpecificOperations();
2714 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002715
Caroline Tice713c2662011-02-11 17:59:55 +00002716 for i = 0 to 14
2717 if registers<i> == ’1’ then
2718 R[i] = MemA[address,4]; address = address + 4;
2719
2720 if registers<15> == ’1’ then
2721 LoadWritePC(MemA[address,4]);
2722
2723 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2724 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2725#endif
2726
2727 bool success = false;
2728 const uint32_t opcode = OpcodeAsUnsigned (&success);
2729 if (!success)
2730 return false;
2731
2732 if (ConditionPassed())
2733 {
2734 uint32_t n;
2735 uint32_t registers = 0;
2736 bool wback;
2737 const uint32_t addr_byte_size = GetAddressByteSize();
2738
2739 // EncodingSpecificOperations();
2740 switch (encoding)
2741 {
2742 case eEncodingA1:
2743 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2744 n = Bits32 (opcode, 19, 16);
2745 registers = Bits32 (opcode, 15, 0);
2746 wback = BitIsSet (opcode, 21);
2747
2748 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2749 if ((n == 15) || (BitCount (registers) < 1))
2750 return false;
2751
2752 break;
2753
2754 default:
2755 return false;
2756 }
2757 // address = R[n] - 4*BitCount(registers) + 4;
2758
2759 int32_t offset = 0;
2760 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2761
2762 if (!success)
2763 return false;
2764
2765 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2766
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002767 EmulateInstruction::Context context;
2768 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2769 Register dwarf_reg;
2770 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2771 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002772
2773 // for i = 0 to 14
2774 for (int i = 0; i < 14; ++i)
2775 {
2776 // if registers<i> == ’1’ then
2777 if (BitIsSet (registers, i))
2778 {
2779 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002780 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002781 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002782 if (!success)
2783 return false;
2784 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2785 return false;
2786 offset += addr_byte_size;
2787 }
2788 }
2789
2790 // if registers<15> == ’1’ then
2791 // LoadWritePC(MemA[address,4]);
2792 if (BitIsSet (registers, 15))
2793 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002794 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002795 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002796 if (!success)
2797 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002798 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002799 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002800 return false;
2801 }
2802
2803 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2804 if (wback && BitIsClear (registers, n))
2805 {
Caroline Tice713c2662011-02-11 17:59:55 +00002806 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2807 if (!success)
2808 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002809
2810 offset = (addr_byte_size * BitCount (registers)) * -1;
2811 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002812 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002813 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002814 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2815 return false;
2816 }
2817
2818 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2819 if (wback && BitIsSet (registers, n))
2820 return WriteBits32Unknown (n);
2821 }
2822 return true;
2823}
2824
2825// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2826// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2827// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002828bool
2829EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2830{
2831#if 0
2832 // ARM pseudo code...
2833 if ConditionPassed() then
2834 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2835 address = R[n] - 4*BitCount(registers);
2836
2837 for i = 0 to 14
2838 if registers<i> == ’1’ then
2839 R[i] = MemA[address,4]; address = address + 4;
2840 if registers<15> == ’1’ then
2841 LoadWritePC(MemA[address,4]);
2842
2843 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2844 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2845#endif
2846
2847 bool success = false;
2848 const uint32_t opcode = OpcodeAsUnsigned (&success);
2849 if (!success)
2850 return false;
2851
2852 if (ConditionPassed())
2853 {
2854 uint32_t n;
2855 uint32_t registers = 0;
2856 bool wback;
2857 const uint32_t addr_byte_size = GetAddressByteSize();
2858 switch (encoding)
2859 {
2860 case eEncodingT1:
2861 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2862 n = Bits32 (opcode, 19, 16);
2863 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002864 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002865 wback = BitIsSet (opcode, 21);
2866
2867 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2868 if ((n == 15)
2869 || (BitCount (registers) < 2)
2870 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2871 return false;
2872
2873 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002874 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002875 return false;
2876
2877 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2878 if (wback && BitIsSet (registers, n))
2879 return false;
2880
2881 break;
2882
2883 case eEncodingA1:
2884 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2885 n = Bits32 (opcode, 19, 16);
2886 registers = Bits32 (opcode, 15, 0);
2887 wback = BitIsSet (opcode, 21);
2888
2889 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2890 if ((n == 15) || (BitCount (registers) < 1))
2891 return false;
2892
2893 break;
2894
2895 default:
2896 return false;
2897 }
2898
Caroline Tice713c2662011-02-11 17:59:55 +00002899 // address = R[n] - 4*BitCount(registers);
2900
Caroline Tice0b29e242011-02-08 23:16:02 +00002901 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002902 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2903
2904 if (!success)
2905 return false;
2906
2907 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002908 EmulateInstruction::Context context;
2909 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2910 Register dwarf_reg;
2911 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2912 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002913
2914 for (int i = 0; i < 14; ++i)
2915 {
2916 if (BitIsSet (registers, i))
2917 {
2918 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002919 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002920 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002921 if (!success)
2922 return false;
2923
2924 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2925 return false;
2926
2927 offset += addr_byte_size;
2928 }
2929 }
2930
2931 // if registers<15> == ’1’ then
2932 // LoadWritePC(MemA[address,4]);
2933 if (BitIsSet (registers, 15))
2934 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002935 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002936 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002937 if (!success)
2938 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002939 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002940 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002941 return false;
2942 }
2943
2944 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2945 if (wback && BitIsClear (registers, n))
2946 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002947 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2948 if (!success)
2949 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002950
2951 offset = (addr_byte_size * BitCount (registers)) * -1;
2952 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002953 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002954 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2956 return false;
2957 }
2958
2959 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2960 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002961 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002962 }
2963 return true;
2964}
Caroline Tice85aab332011-02-08 23:56:10 +00002965
Caroline Tice713c2662011-02-11 17:59:55 +00002966// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2967// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2968// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002969bool
2970EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2971{
2972#if 0
2973 if ConditionPassed() then
2974 EncodingSpecificOperations();
2975 address = R[n] + 4;
2976
2977 for i = 0 to 14
2978 if registers<i> == ’1’ then
2979 R[i] = MemA[address,4]; address = address + 4;
2980 if registers<15> == ’1’ then
2981 LoadWritePC(MemA[address,4]);
2982
2983 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2984 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2985#endif
2986
2987 bool success = false;
2988 const uint32_t opcode = OpcodeAsUnsigned (&success);
2989 if (!success)
2990 return false;
2991
2992 if (ConditionPassed())
2993 {
2994 uint32_t n;
2995 uint32_t registers = 0;
2996 bool wback;
2997 const uint32_t addr_byte_size = GetAddressByteSize();
2998 switch (encoding)
2999 {
3000 case eEncodingA1:
3001 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3002 n = Bits32 (opcode, 19, 16);
3003 registers = Bits32 (opcode, 15, 0);
3004 wback = BitIsSet (opcode, 21);
3005
3006 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3007 if ((n == 15) || (BitCount (registers) < 1))
3008 return false;
3009
3010 break;
3011 default:
3012 return false;
3013 }
3014 // address = R[n] + 4;
3015
3016 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003017 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3018
3019 if (!success)
3020 return false;
3021
3022 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003023
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003024 EmulateInstruction::Context context;
3025 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3026 Register dwarf_reg;
3027 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3028 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003029
3030 for (int i = 0; i < 14; ++i)
3031 {
3032 if (BitIsSet (registers, i))
3033 {
3034 // R[i] = MemA[address,4]; address = address + 4;
3035
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003036 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003037 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003038 if (!success)
3039 return false;
3040
3041 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3042 return false;
3043
3044 offset += addr_byte_size;
3045 }
3046 }
3047
3048 // if registers<15> == ’1’ then
3049 // LoadWritePC(MemA[address,4]);
3050 if (BitIsSet (registers, 15))
3051 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003052 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003053 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003054 if (!success)
3055 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003056 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003057 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003058 return false;
3059 }
3060
3061 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3062 if (wback && BitIsClear (registers, n))
3063 {
Caroline Tice85aab332011-02-08 23:56:10 +00003064 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3065 if (!success)
3066 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003067
3068 offset = addr_byte_size * BitCount (registers);
3069 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003070 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003071 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003072 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3073 return false;
3074 }
3075
3076 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3077 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003078 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003079 }
3080 return true;
3081}
Caroline Tice0b29e242011-02-08 23:16:02 +00003082
Johnny Chenef21b592011-02-10 01:52:38 +00003083// Load Register (immediate) calculates an address from a base register value and
3084// an immediate offset, loads a word from memory, and writes to a register.
3085// LDR (immediate, Thumb)
3086bool
3087EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3088{
3089#if 0
3090 // ARM pseudo code...
3091 if (ConditionPassed())
3092 {
3093 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3094 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3095 address = if index then offset_addr else R[n];
3096 data = MemU[address,4];
3097 if wback then R[n] = offset_addr;
3098 if t == 15 then
3099 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3100 elsif UnalignedSupport() || address<1:0> = '00' then
3101 R[t] = data;
3102 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3103 }
3104#endif
3105
3106 bool success = false;
3107 const uint32_t opcode = OpcodeAsUnsigned (&success);
3108 if (!success)
3109 return false;
3110
3111 if (ConditionPassed())
3112 {
3113 uint32_t Rt; // the destination register
3114 uint32_t Rn; // the base register
3115 uint32_t imm32; // the immediate offset used to form the address
3116 addr_t offset_addr; // the offset address
3117 addr_t address; // the calculated address
3118 uint32_t data; // the literal data value from memory load
3119 bool add, index, wback;
3120 switch (encoding) {
3121 case eEncodingT1:
3122 Rt = Bits32(opcode, 5, 3);
3123 Rn = Bits32(opcode, 2, 0);
3124 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3125 // index = TRUE; add = TRUE; wback = FALSE
3126 add = true;
3127 index = true;
3128 wback = false;
3129 break;
3130 default:
3131 return false;
3132 }
3133 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3134 if (!success)
3135 return false;
3136 if (add)
3137 offset_addr = base + imm32;
3138 else
3139 offset_addr = base - imm32;
3140
3141 address = (index ? offset_addr : base);
3142
3143 if (wback)
3144 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003145 EmulateInstruction::Context ctx;
3146 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3147 Register dwarf_reg;
3148 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3149 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3150
Johnny Chenef21b592011-02-10 01:52:38 +00003151 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3152 return false;
3153 }
3154
3155 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003156 EmulateInstruction::Context context;
3157 context.type = EmulateInstruction::eContextImmediate;
3158 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003159
3160 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003161 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003162 if (!success)
3163 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003164
3165 if (Rt == 15)
3166 {
3167 if (Bits32(address, 1, 0) == 0)
3168 {
Johnny Chen668b4512011-02-15 21:08:58 +00003169 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003170 return false;
3171 }
3172 else
3173 return false;
3174 }
3175 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3176 {
3177 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3178 return false;
3179 }
3180 else
3181 return false;
3182 }
3183 return true;
3184}
3185
Caroline Ticeaf556562011-02-15 18:42:15 +00003186// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3187// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3188// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003189bool
3190EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3191{
3192#if 0
3193 if ConditionPassed() then
3194 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3195 address = R[n];
3196
3197 for i = 0 to 14
3198 if registers<i> == ’1’ then
3199 if i == n && wback && i != LowestSetBit(registers) then
3200 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3201 else
3202 MemA[address,4] = R[i];
3203 address = address + 4;
3204
3205 if registers<15> == ’1’ then // Only possible for encoding A1
3206 MemA[address,4] = PCStoreValue();
3207 if wback then R[n] = R[n] + 4*BitCount(registers);
3208#endif
3209
3210 bool success = false;
3211 const uint32_t opcode = OpcodeAsUnsigned (&success);
3212 if (!success)
3213 return false;
3214
3215 if (ConditionPassed ())
3216 {
3217 uint32_t n;
3218 uint32_t registers = 0;
3219 bool wback;
3220 const uint32_t addr_byte_size = GetAddressByteSize();
3221
3222 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3223 switch (encoding)
3224 {
3225 case eEncodingT1:
3226 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3227 n = Bits32 (opcode, 10, 8);
3228 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003229 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003230 wback = true;
3231
3232 // if BitCount(registers) < 1 then UNPREDICTABLE;
3233 if (BitCount (registers) < 1)
3234 return false;
3235
3236 break;
3237
3238 case eEncodingT2:
3239 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3240 n = Bits32 (opcode, 19, 16);
3241 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003242 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003243 wback = BitIsSet (opcode, 21);
3244
3245 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3246 if ((n == 15) || (BitCount (registers) < 2))
3247 return false;
3248
3249 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3250 if (wback && BitIsSet (registers, n))
3251 return false;
3252
3253 break;
3254
3255 case eEncodingA1:
3256 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3257 n = Bits32 (opcode, 19, 16);
3258 registers = Bits32 (opcode, 15, 0);
3259 wback = BitIsSet (opcode, 21);
3260
3261 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3262 if ((n == 15) || (BitCount (registers) < 1))
3263 return false;
3264
3265 break;
3266
3267 default:
3268 return false;
3269 }
3270
3271 // address = R[n];
3272 int32_t offset = 0;
3273 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3274 if (!success)
3275 return false;
3276
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003277 EmulateInstruction::Context context;
3278 context.type = EmulateInstruction::eContextRegisterStore;
3279 Register base_reg;
3280 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003281
3282 // for i = 0 to 14
3283 for (int i = 0; i < 14; ++i)
3284 {
3285 int lowest_set_bit = 14;
3286 // if registers<i> == ’1’ then
3287 if (BitIsSet (registers, i))
3288 {
3289 if (i < lowest_set_bit)
3290 lowest_set_bit = i;
3291 // if i == n && wback && i != LowestSetBit(registers) then
3292 if ((i == n) && wback && (i != lowest_set_bit))
3293 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3294 WriteBits32UnknownToMemory (address + offset);
3295 else
3296 {
3297 // MemA[address,4] = R[i];
3298 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3299 if (!success)
3300 return false;
3301
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003302 Register data_reg;
3303 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3304 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003305 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003306 return false;
3307 }
3308
3309 // address = address + 4;
3310 offset += addr_byte_size;
3311 }
3312 }
3313
3314 // if registers<15> == ’1’ then // Only possible for encoding A1
3315 // MemA[address,4] = PCStoreValue();
3316 if (BitIsSet (registers, 15))
3317 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003318 Register pc_reg;
3319 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3320 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003321 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3322 if (!success)
3323 return false;
3324
Caroline Ticecc96eb52011-02-17 19:20:40 +00003325 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003326 return false;
3327 }
3328
3329 // if wback then R[n] = R[n] + 4*BitCount(registers);
3330 if (wback)
3331 {
3332 offset = addr_byte_size * BitCount (registers);
3333 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003334 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003335 addr_t data = address + offset;
3336 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3337 return false;
3338 }
3339 }
3340 return true;
3341}
3342
Caroline Ticeaf556562011-02-15 18:42:15 +00003343// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3344// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3345// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003346bool
3347EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3348{
3349#if 0
3350 if ConditionPassed() then
3351 EncodingSpecificOperations();
3352 address = R[n] - 4*BitCount(registers) + 4;
3353
3354 for i = 0 to 14
3355 if registers<i> == ’1’ then
3356 if i == n && wback && i != LowestSetBit(registers) then
3357 MemA[address,4] = bits(32) UNKNOWN;
3358 else
3359 MemA[address,4] = R[i];
3360 address = address + 4;
3361
3362 if registers<15> == ’1’ then
3363 MemA[address,4] = PCStoreValue();
3364
3365 if wback then R[n] = R[n] - 4*BitCount(registers);
3366#endif
3367
3368 bool success = false;
3369 const uint32_t opcode = OpcodeAsUnsigned (&success);
3370 if (!success)
3371 return false;
3372
3373 if (ConditionPassed ())
3374 {
3375 uint32_t n;
3376 uint32_t registers = 0;
3377 bool wback;
3378 const uint32_t addr_byte_size = GetAddressByteSize();
3379
3380 // EncodingSpecificOperations();
3381 switch (encoding)
3382 {
3383 case eEncodingA1:
3384 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3385 n = Bits32 (opcode, 19, 16);
3386 registers = Bits32 (opcode, 15, 0);
3387 wback = BitIsSet (opcode, 21);
3388
3389 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3390 if ((n == 15) || (BitCount (registers) < 1))
3391 return false;
3392 break;
3393 default:
3394 return false;
3395 }
3396
3397 // address = R[n] - 4*BitCount(registers) + 4;
3398 int32_t offset = 0;
3399 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3400 if (!success)
3401 return false;
3402
3403 address = address - (addr_byte_size * BitCount (registers)) + 4;
3404
3405 EmulateInstruction::Context context;
3406 context.type = EmulateInstruction::eContextRegisterStore;
3407 Register base_reg;
3408 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3409
3410 // for i = 0 to 14
3411 for (int i = 0; i < 14; ++i)
3412 {
3413 int lowest_bit_set = 14;
3414 // if registers<i> == ’1’ then
3415 if (BitIsSet (registers, i))
3416 {
3417 if (i < lowest_bit_set)
3418 lowest_bit_set = i;
3419 //if i == n && wback && i != LowestSetBit(registers) then
3420 if ((i == n) && wback && (i != lowest_bit_set))
3421 // MemA[address,4] = bits(32) UNKNOWN;
3422 WriteBits32UnknownToMemory (address + offset);
3423 else
3424 {
3425 // MemA[address,4] = R[i];
3426 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3427 if (!success)
3428 return false;
3429
3430 Register data_reg;
3431 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3432 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003433 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003434 return false;
3435 }
3436
3437 // address = address + 4;
3438 offset += addr_byte_size;
3439 }
3440 }
3441
3442 // if registers<15> == ’1’ then
3443 // MemA[address,4] = PCStoreValue();
3444 if (BitIsSet (registers, 15))
3445 {
3446 Register pc_reg;
3447 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3448 context.SetRegisterPlusOffset (pc_reg, 8);
3449 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3450 if (!success)
3451 return false;
3452
Caroline Ticecc96eb52011-02-17 19:20:40 +00003453 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003454 return false;
3455 }
3456
3457 // if wback then R[n] = R[n] - 4*BitCount(registers);
3458 if (wback)
3459 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003460 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003461 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3462 context.SetImmediateSigned (offset);
3463 addr_t data = address + offset;
3464 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3465 return false;
3466 }
3467 }
3468 return true;
3469}
3470
Caroline Ticeaf556562011-02-15 18:42:15 +00003471// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3472// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3473// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003474bool
3475EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3476{
3477#if 0
3478 if ConditionPassed() then
3479 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3480 address = R[n] - 4*BitCount(registers);
3481
3482 for i = 0 to 14
3483 if registers<i> == ’1’ then
3484 if i == n && wback && i != LowestSetBit(registers) then
3485 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3486 else
3487 MemA[address,4] = R[i];
3488 address = address + 4;
3489
3490 if registers<15> == ’1’ then // Only possible for encoding A1
3491 MemA[address,4] = PCStoreValue();
3492
3493 if wback then R[n] = R[n] - 4*BitCount(registers);
3494#endif
3495
3496
3497 bool success = false;
3498 const uint32_t opcode = OpcodeAsUnsigned (&success);
3499 if (!success)
3500 return false;
3501
3502 if (ConditionPassed ())
3503 {
3504 uint32_t n;
3505 uint32_t registers = 0;
3506 bool wback;
3507 const uint32_t addr_byte_size = GetAddressByteSize();
3508
3509 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3510 switch (encoding)
3511 {
3512 case eEncodingT1:
3513 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3514 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3515 {
3516 // See PUSH
3517 }
3518 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3519 n = Bits32 (opcode, 19, 16);
3520 registers = Bits32 (opcode, 15, 0);
3521 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3522 wback = BitIsSet (opcode, 21);
3523 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3524 if ((n == 15) || BitCount (registers) < 2)
3525 return false;
3526 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3527 if (wback && BitIsSet (registers, n))
3528 return false;
3529 break;
3530
3531 case eEncodingA1:
3532 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3533 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3534 {
3535 // See Push
3536 }
3537 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3538 n = Bits32 (opcode, 19, 16);
3539 registers = Bits32 (opcode, 15, 0);
3540 wback = BitIsSet (opcode, 21);
3541 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3542 if ((n == 15) || BitCount (registers) < 1)
3543 return false;
3544 break;
3545
3546 default:
3547 return false;
3548 }
3549
3550 // address = R[n] - 4*BitCount(registers);
3551
3552 int32_t offset = 0;
3553 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3554 if (!success)
3555 return false;
3556
3557 address = address - (addr_byte_size * BitCount (registers));
3558
3559 EmulateInstruction::Context context;
3560 context.type = EmulateInstruction::eContextRegisterStore;
3561 Register base_reg;
3562 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3563
3564 // for i = 0 to 14
3565 for (int i = 0; i < 14; ++i)
3566 {
3567 uint32_t lowest_set_bit = 14;
3568 // if registers<i> == ’1’ then
3569 if (BitIsSet (registers, i))
3570 {
3571 if (i < lowest_set_bit)
3572 lowest_set_bit = i;
3573 // if i == n && wback && i != LowestSetBit(registers) then
3574 if ((i == n) && wback && (i != lowest_set_bit))
3575 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3576 WriteBits32UnknownToMemory (address + offset);
3577 else
3578 {
3579 // MemA[address,4] = R[i];
3580 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3581 if (!success)
3582 return false;
3583
3584 Register data_reg;
3585 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3586 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003587 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003588 return false;
3589 }
3590
3591 // address = address + 4;
3592 offset += addr_byte_size;
3593 }
3594 }
3595
3596 // if registers<15> == ’1’ then // Only possible for encoding A1
3597 // MemA[address,4] = PCStoreValue();
3598 if (BitIsSet (registers, 15))
3599 {
3600 Register pc_reg;
3601 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3602 context.SetRegisterPlusOffset (pc_reg, 8);
3603 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3604 if (!success)
3605 return false;
3606
Caroline Ticecc96eb52011-02-17 19:20:40 +00003607 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003608 return false;
3609 }
3610
3611 // if wback then R[n] = R[n] - 4*BitCount(registers);
3612 if (wback)
3613 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003614 offset = (addr_byte_size * BitCount (registers)) * -1;
3615 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3616 context.SetImmediateSigned (offset);
3617 addr_t data = address + offset;
3618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3619 return false;
3620 }
3621 }
3622 return true;
3623}
3624
3625// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3626// from a base register. The consecutive memory locations start just above this address, and the address of the last
3627// of those locations can optionally be written back to the base register.
3628bool
3629EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3630{
3631#if 0
3632 if ConditionPassed() then
3633 EncodingSpecificOperations();
3634 address = R[n] + 4;
3635
3636 for i = 0 to 14
3637 if registers<i> == ’1’ then
3638 if i == n && wback && i != LowestSetBit(registers) then
3639 MemA[address,4] = bits(32) UNKNOWN;
3640 else
3641 MemA[address,4] = R[i];
3642 address = address + 4;
3643
3644 if registers<15> == ’1’ then
3645 MemA[address,4] = PCStoreValue();
3646
3647 if wback then R[n] = R[n] + 4*BitCount(registers);
3648#endif
3649
3650 bool success = false;
3651 const uint32_t opcode = OpcodeAsUnsigned (&success);
3652 if (!success)
3653 return false;
3654
3655 if (ConditionPassed())
3656 {
3657 uint32_t n;
3658 uint32_t registers = 0;
3659 bool wback;
3660 const uint32_t addr_byte_size = GetAddressByteSize();
3661
3662 // EncodingSpecificOperations();
3663 switch (encoding)
3664 {
3665 case eEncodingA1:
3666 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3667 n = Bits32 (opcode, 19, 16);
3668 registers = Bits32 (opcode, 15, 0);
3669 wback = BitIsSet (opcode, 21);
3670
3671 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3672 if ((n == 15) && (BitCount (registers) < 1))
3673 return false;
3674 break;
3675 default:
3676 return false;
3677 }
3678 // address = R[n] + 4;
3679
3680 int32_t offset = 0;
3681 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3682 if (!success)
3683 return false;
3684
3685 address = address + addr_byte_size;
3686
3687 EmulateInstruction::Context context;
3688 context.type = EmulateInstruction::eContextRegisterStore;
3689 Register base_reg;
3690 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3691
3692 uint32_t lowest_set_bit = 14;
3693 // for i = 0 to 14
3694 for (int i = 0; i < 14; ++i)
3695 {
3696 // if registers<i> == ’1’ then
3697 if (BitIsSet (registers, i))
3698 {
3699 if (i < lowest_set_bit)
3700 lowest_set_bit = i;
3701 // if i == n && wback && i != LowestSetBit(registers) then
3702 if ((i == n) && wback && (i != lowest_set_bit))
3703 // MemA[address,4] = bits(32) UNKNOWN;
3704 WriteBits32UnknownToMemory (address + offset);
3705 // else
3706 else
3707 {
3708 // MemA[address,4] = R[i];
3709 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3710 if (!success)
3711 return false;
3712
3713 Register data_reg;
3714 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3715 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003716 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003717 return false;
3718 }
3719
3720 // address = address + 4;
3721 offset += addr_byte_size;
3722 }
3723 }
3724
3725 // if registers<15> == ’1’ then
3726 // MemA[address,4] = PCStoreValue();
3727 if (BitIsSet (registers, 15))
3728 {
3729 Register pc_reg;
3730 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3731 context.SetRegisterPlusOffset (pc_reg, 8);
3732 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3733 if (!success)
3734 return false;
3735
Caroline Ticecc96eb52011-02-17 19:20:40 +00003736 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003737 return false;
3738 }
3739
3740 // if wback then R[n] = R[n] + 4*BitCount(registers);
3741 if (wback)
3742 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003743 offset = addr_byte_size * BitCount (registers);
3744 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3745 context.SetImmediateSigned (offset);
3746 addr_t data = address + offset;
3747 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3748 return false;
3749 }
3750 }
3751 return true;
3752}
Caroline Tice7fac8572011-02-15 22:53:54 +00003753
3754// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3755// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3756bool
3757EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3758{
3759#if 0
3760 if ConditionPassed() then
3761 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3762 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3763 address = if index then offset_addr else R[n];
3764 if UnalignedSupport() || address<1:0> == ’00’ then
3765 MemU[address,4] = R[t];
3766 else // Can only occur before ARMv7
3767 MemU[address,4] = bits(32) UNKNOWN;
3768 if wback then R[n] = offset_addr;
3769#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003770
Caroline Tice7fac8572011-02-15 22:53:54 +00003771 bool success = false;
3772 const uint32_t opcode = OpcodeAsUnsigned (&success);
3773 if (!success)
3774 return false;
3775
3776 if (ConditionPassed())
3777 {
3778 const uint32_t addr_byte_size = GetAddressByteSize();
3779
3780 uint32_t t;
3781 uint32_t n;
3782 uint32_t imm32;
3783 bool index;
3784 bool add;
3785 bool wback;
3786 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3787 switch (encoding)
3788 {
3789 case eEncodingT1:
3790 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3791 t = Bits32 (opcode, 2, 0);
3792 n = Bits32 (opcode, 5, 3);
3793 imm32 = Bits32 (opcode, 10, 6) << 2;
3794
3795 // index = TRUE; add = TRUE; wback = FALSE;
3796 index = true;
3797 add = false;
3798 wback = false;
3799 break;
3800
3801 case eEncodingT2:
3802 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3803 t = Bits32 (opcode, 10, 8);
3804 n = 13;
3805 imm32 = Bits32 (opcode, 7, 0) << 2;
3806
3807 // index = TRUE; add = TRUE; wback = FALSE;
3808 index = true;
3809 add = true;
3810 wback = false;
3811 break;
3812
3813 case eEncodingT3:
3814 // if Rn == ’1111’ then UNDEFINED;
3815 if (Bits32 (opcode, 19, 16) == 15)
3816 return false;
3817
3818 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3819 t = Bits32 (opcode, 15, 12);
3820 n = Bits32 (opcode, 19, 16);
3821 imm32 = Bits32 (opcode, 11, 0);
3822
3823 // index = TRUE; add = TRUE; wback = FALSE;
3824 index = true;
3825 add = true;
3826 wback = false;
3827
3828 // if t == 15 then UNPREDICTABLE;
3829 if (t == 15)
3830 return false;
3831 break;
3832
3833 case eEncodingT4:
3834 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3835 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3836 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3837 if ((Bits32 (opcode, 19, 16) == 15)
3838 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3839 return false;
3840
3841 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3842 t = Bits32 (opcode, 15, 12);
3843 n = Bits32 (opcode, 19, 16);
3844 imm32 = Bits32 (opcode, 7, 0);
3845
3846 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3847 index = BitIsSet (opcode, 10);
3848 add = BitIsSet (opcode, 9);
3849 wback = BitIsSet (opcode, 8);
3850
3851 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3852 if ((t == 15) || (wback && (n == t)))
3853 return false;
3854 break;
3855
3856 default:
3857 return false;
3858 }
3859
3860 addr_t offset_addr;
3861 addr_t address;
3862
3863 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3864 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3865 if (!success)
3866 return false;
3867
3868 if (add)
3869 offset_addr = base_address + imm32;
3870 else
3871 offset_addr = base_address - imm32;
3872
3873 // address = if index then offset_addr else R[n];
3874 if (index)
3875 address = offset_addr;
3876 else
3877 address = base_address;
3878
3879 EmulateInstruction::Context context;
3880 context.type = eContextRegisterStore;
3881 Register base_reg;
3882 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3883
3884 // if UnalignedSupport() || address<1:0> == ’00’ then
3885 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3886 {
3887 // MemU[address,4] = R[t];
3888 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3889 if (!success)
3890 return false;
3891
3892 Register data_reg;
3893 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3894 int32_t offset = address - base_address;
3895 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003896 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003897 return false;
3898 }
3899 else
3900 {
3901 // MemU[address,4] = bits(32) UNKNOWN;
3902 WriteBits32UnknownToMemory (address);
3903 }
3904
3905 // if wback then R[n] = offset_addr;
3906 if (wback)
3907 {
3908 context.type = eContextRegisterLoad;
3909 context.SetAddress (offset_addr);
3910 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3911 return false;
3912 }
3913 }
3914 return true;
3915}
Caroline Ticeaf556562011-02-15 18:42:15 +00003916
Caroline Tice3fd63e92011-02-16 00:33:43 +00003917// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3918// word from a register to memory. The offset register value can optionally be shifted.
3919bool
3920EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3921{
3922#if 0
3923 if ConditionPassed() then
3924 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3925 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3926 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3927 address = if index then offset_addr else R[n];
3928 if t == 15 then // Only possible for encoding A1
3929 data = PCStoreValue();
3930 else
3931 data = R[t];
3932 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3933 MemU[address,4] = data;
3934 else // Can only occur before ARMv7
3935 MemU[address,4] = bits(32) UNKNOWN;
3936 if wback then R[n] = offset_addr;
3937#endif
3938
3939 bool success = false;
3940 const uint32_t opcode = OpcodeAsUnsigned (&success);
3941 if (!success)
3942 return false;
3943
3944 if (ConditionPassed())
3945 {
3946 const uint32_t addr_byte_size = GetAddressByteSize();
3947
3948 uint32_t t;
3949 uint32_t n;
3950 uint32_t m;
3951 ARM_ShifterType shift_t;
3952 uint32_t shift_n;
3953 bool index;
3954 bool add;
3955 bool wback;
3956
3957 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3958 switch (encoding)
3959 {
3960 case eEncodingT1:
3961 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3962 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3963 t = Bits32 (opcode, 2, 0);
3964 n = Bits32 (opcode, 5, 3);
3965 m = Bits32 (opcode, 8, 6);
3966
3967 // index = TRUE; add = TRUE; wback = FALSE;
3968 index = true;
3969 add = true;
3970 wback = false;
3971
3972 // (shift_t, shift_n) = (SRType_LSL, 0);
3973 shift_t = SRType_LSL;
3974 shift_n = 0;
3975 break;
3976
3977 case eEncodingT2:
3978 // if Rn == ’1111’ then UNDEFINED;
3979 if (Bits32 (opcode, 19, 16) == 15)
3980 return false;
3981
3982 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3983 t = Bits32 (opcode, 15, 12);
3984 n = Bits32 (opcode, 19, 16);
3985 m = Bits32 (opcode, 3, 0);
3986
3987 // index = TRUE; add = TRUE; wback = FALSE;
3988 index = true;
3989 add = true;
3990 wback = false;
3991
3992 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3993 shift_t = SRType_LSL;
3994 shift_n = Bits32 (opcode, 5, 4);
3995
3996 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3997 if ((t == 15) || (BadReg (m)))
3998 return false;
3999 break;
4000
4001 case eEncodingA1:
4002 {
4003 // if P == ’0’ && W == ’1’ then SEE STRT;
4004 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4005 t = Bits32 (opcode, 15, 12);
4006 n = Bits32 (opcode, 19, 16);
4007 m = Bits32 (opcode, 3, 0);
4008
4009 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4010 index = BitIsSet (opcode, 24);
4011 add = BitIsSet (opcode, 23);
4012 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4013
4014 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4015 uint32_t typ = Bits32 (opcode, 6, 5);
4016 uint32_t imm5 = Bits32 (opcode, 11, 7);
4017 shift_n = DecodeImmShift(typ, imm5, shift_t);
4018
4019 // if m == 15 then UNPREDICTABLE;
4020 if (m == 15)
4021 return false;
4022
4023 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4024 if (wback && ((n == 15) || (n == t)))
4025 return false;
4026
4027 break;
4028 }
4029 default:
4030 return false;
4031 }
4032
4033 addr_t offset_addr;
4034 addr_t address;
4035 int32_t offset = 0;
4036
4037 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4038 if (!success)
4039 return false;
4040
4041 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4042 if (!success)
4043 return false;
4044
4045 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004046 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004047
4048 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4049 if (add)
4050 offset_addr = base_address + offset;
4051 else
4052 offset_addr = base_address - offset;
4053
4054 // address = if index then offset_addr else R[n];
4055 if (index)
4056 address = offset_addr;
4057 else
4058 address = base_address;
4059
4060 uint32_t data;
4061 // if t == 15 then // Only possible for encoding A1
4062 if (t == 15)
4063 // data = PCStoreValue();
4064 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4065 else
4066 // data = R[t];
4067 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4068
4069 if (!success)
4070 return false;
4071
4072 EmulateInstruction::Context context;
4073 context.type = eContextRegisterStore;
4074
4075 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4076 if (UnalignedSupport ()
4077 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4078 || CurrentInstrSet() == eModeARM)
4079 {
4080 // MemU[address,4] = data;
4081
4082 Register base_reg;
4083 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4084
4085 Register data_reg;
4086 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4087
4088 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004089 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004090 return false;
4091
4092 }
4093 else
4094 // MemU[address,4] = bits(32) UNKNOWN;
4095 WriteBits32UnknownToMemory (address);
4096
4097 // if wback then R[n] = offset_addr;
4098 if (wback)
4099 {
4100 context.type = eContextRegisterLoad;
4101 context.SetAddress (offset_addr);
4102 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4103 return false;
4104 }
4105
4106 }
4107 return true;
4108}
Caroline Tice73a29de2011-02-16 20:22:22 +00004109
4110bool
4111EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4112{
4113#if 0
4114 if ConditionPassed() then
4115 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4116 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4117 address = if index then offset_addr else R[n];
4118 MemU[address,1] = R[t]<7:0>;
4119 if wback then R[n] = offset_addr;
4120#endif
4121
4122
4123 bool success = false;
4124 const uint32_t opcode = OpcodeAsUnsigned (&success);
4125 if (!success)
4126 return false;
4127
4128 if (ConditionPassed ())
4129 {
4130 uint32_t t;
4131 uint32_t n;
4132 uint32_t imm32;
4133 bool index;
4134 bool add;
4135 bool wback;
4136 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4137 switch (encoding)
4138 {
4139 case eEncodingT1:
4140 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4141 t = Bits32 (opcode, 2, 0);
4142 n = Bits32 (opcode, 5, 3);
4143 imm32 = Bits32 (opcode, 10, 6);
4144
4145 // index = TRUE; add = TRUE; wback = FALSE;
4146 index = true;
4147 add = true;
4148 wback = false;
4149 break;
4150
4151 case eEncodingT2:
4152 // if Rn == ’1111’ then UNDEFINED;
4153 if (Bits32 (opcode, 19, 16) == 15)
4154 return false;
4155
4156 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4157 t = Bits32 (opcode, 15, 12);
4158 n = Bits32 (opcode, 19, 16);
4159 imm32 = Bits32 (opcode, 11, 0);
4160
4161 // index = TRUE; add = TRUE; wback = FALSE;
4162 index = true;
4163 add = true;
4164 wback = false;
4165
4166 // if BadReg(t) then UNPREDICTABLE;
4167 if (BadReg (t))
4168 return false;
4169 break;
4170
4171 case eEncodingT3:
4172 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4173 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4174 if (Bits32 (opcode, 19, 16) == 15)
4175 return false;
4176
4177 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4178 t = Bits32 (opcode, 15, 12);
4179 n = Bits32 (opcode, 19, 16);
4180 imm32 = Bits32 (opcode, 7, 0);
4181
4182 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4183 index = BitIsSet (opcode, 10);
4184 add = BitIsSet (opcode, 9);
4185 wback = BitIsSet (opcode, 8);
4186
4187 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4188 if ((BadReg (t)) || (wback && (n == t)))
4189 return false;
4190 break;
4191
4192 default:
4193 return false;
4194 }
4195
4196 addr_t offset_addr;
4197 addr_t address;
4198 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4199 if (!success)
4200 return false;
4201
4202 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4203 if (add)
4204 offset_addr = base_address + imm32;
4205 else
4206 offset_addr = base_address - imm32;
4207
4208 // address = if index then offset_addr else R[n];
4209 if (index)
4210 address = offset_addr;
4211 else
4212 address = base_address;
4213
Caroline Ticecc96eb52011-02-17 19:20:40 +00004214 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004215 Register base_reg;
4216 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4217
4218 Register data_reg;
4219 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4220
4221 EmulateInstruction::Context context;
4222 context.type = eContextRegisterStore;
4223 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4224
4225 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4226 if (!success)
4227 return false;
4228
4229 data = Bits32 (data, 7, 0);
4230
Caroline Ticecc96eb52011-02-17 19:20:40 +00004231 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004232 return false;
4233
4234 // if wback then R[n] = offset_addr;
4235 if (wback)
4236 {
4237 context.type = eContextRegisterLoad;
4238 context.SetAddress (offset_addr);
4239 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4240 return false;
4241 }
4242
4243 }
4244
4245 return true;
4246}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004247
Johnny Chen157b9592011-02-18 21:13:05 +00004248// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4249// and writes the result to the destination register. It can optionally update the condition flags
4250// based on the result.
4251bool
4252EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4253{
4254#if 0
4255 // ARM pseudo code...
4256 if ConditionPassed() then
4257 EncodingSpecificOperations();
4258 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4259 if d == 15 then // Can only occur for ARM encoding
4260 ALUWritePC(result); // setflags is always FALSE here
4261 else
4262 R[d] = result;
4263 if setflags then
4264 APSR.N = result<31>;
4265 APSR.Z = IsZeroBit(result);
4266 APSR.C = carry;
4267 APSR.V = overflow;
4268#endif
4269
4270 bool success = false;
4271 const uint32_t opcode = OpcodeAsUnsigned (&success);
4272 if (!success)
4273 return false;
4274
4275 if (ConditionPassed())
4276 {
4277 uint32_t Rd, Rn;
4278 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4279 bool setflags;
4280 switch (encoding)
4281 {
4282 case eEncodingT1:
4283 Rd = Bits32(opcode, 11, 8);
4284 Rn = Bits32(opcode, 19, 16);
4285 setflags = BitIsSet(opcode, 20);
4286 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4287 if (BadReg(Rd) || BadReg(Rn))
4288 return false;
4289 break;
4290 case eEncodingA1:
4291 Rd = Bits32(opcode, 15, 12);
4292 Rn = Bits32(opcode, 19, 16);
4293 setflags = BitIsSet(opcode, 20);
4294 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4295 // TODO: Emulate SUBS PC, LR and related instructions.
4296 if (Rd == 15 && setflags)
4297 return false;
4298 break;
4299 default:
4300 return false;
4301 }
4302
4303 // Read the first operand.
4304 int32_t val1 = ReadCoreReg(Rn, &success);
4305 if (!success)
4306 return false;
4307
4308 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4309
4310 EmulateInstruction::Context context;
4311 context.type = EmulateInstruction::eContextImmediate;
4312 context.SetNoArgs ();
4313
4314 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4315 return false;
4316 }
4317 return true;
4318}
4319
4320// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4321// register value, and writes the result to the destination register. It can optionally update the
4322// condition flags based on the result.
4323bool
4324EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4325{
4326#if 0
4327 // ARM pseudo code...
4328 if ConditionPassed() then
4329 EncodingSpecificOperations();
4330 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4331 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4332 if d == 15 then // Can only occur for ARM encoding
4333 ALUWritePC(result); // setflags is always FALSE here
4334 else
4335 R[d] = result;
4336 if setflags then
4337 APSR.N = result<31>;
4338 APSR.Z = IsZeroBit(result);
4339 APSR.C = carry;
4340 APSR.V = overflow;
4341#endif
4342
4343 bool success = false;
4344 const uint32_t opcode = OpcodeAsUnsigned (&success);
4345 if (!success)
4346 return false;
4347
4348 if (ConditionPassed())
4349 {
4350 uint32_t Rd, Rn, Rm;
4351 ARM_ShifterType shift_t;
4352 uint32_t shift_n; // the shift applied to the value read from Rm
4353 bool setflags;
4354 switch (encoding)
4355 {
4356 case eEncodingT1:
4357 Rd = Rn = Bits32(opcode, 2, 0);
4358 Rm = Bits32(opcode, 5, 3);
4359 setflags = !InITBlock();
4360 shift_t = SRType_LSL;
4361 shift_n = 0;
4362 case eEncodingT2:
4363 Rd = Bits32(opcode, 11, 8);
4364 Rn = Bits32(opcode, 19, 16);
4365 Rm = Bits32(opcode, 3, 0);
4366 setflags = BitIsSet(opcode, 20);
4367 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
4368 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4369 return false;
4370 break;
4371 case eEncodingA1:
4372 Rd = Bits32(opcode, 15, 12);
4373 Rn = Bits32(opcode, 19, 16);
4374 Rm = Bits32(opcode, 3, 0);
4375 setflags = BitIsSet(opcode, 20);
4376 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4377 // TODO: Emulate SUBS PC, LR and related instructions.
4378 if (Rd == 15 && setflags)
4379 return false;
4380 break;
4381 default:
4382 return false;
4383 }
4384
4385 // Read the first operand.
4386 int32_t val1 = ReadCoreReg(Rn, &success);
4387 if (!success)
4388 return false;
4389
4390 // Read the second operand.
4391 int32_t val2 = ReadCoreReg(Rm, &success);
4392 if (!success)
4393 return false;
4394
4395 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4396 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4397
4398 EmulateInstruction::Context context;
4399 context.type = EmulateInstruction::eContextImmediate;
4400 context.SetNoArgs ();
4401
4402 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4403 return false;
4404 }
4405 return true;
4406}
4407
Johnny Chene97c0d52011-02-18 19:32:20 +00004408// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4409// to the destination register. It can optionally update the condition flags based on the result.
4410bool
4411EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4412{
4413#if 0
4414 // ARM pseudo code...
4415 if ConditionPassed() then
4416 EncodingSpecificOperations();
4417 result = R[n] AND imm32;
4418 if d == 15 then // Can only occur for ARM encoding
4419 ALUWritePC(result); // setflags is always FALSE here
4420 else
4421 R[d] = result;
4422 if setflags then
4423 APSR.N = result<31>;
4424 APSR.Z = IsZeroBit(result);
4425 APSR.C = carry;
4426 // APSR.V unchanged
4427#endif
4428
4429 bool success = false;
4430 const uint32_t opcode = OpcodeAsUnsigned (&success);
4431 if (!success)
4432 return false;
4433
4434 if (ConditionPassed())
4435 {
4436 uint32_t Rd, Rn;
4437 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4438 bool setflags;
4439 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4440 switch (encoding)
4441 {
4442 case eEncodingT1:
4443 Rd = Bits32(opcode, 11, 8);
4444 Rn = Bits32(opcode, 19, 16);
4445 setflags = BitIsSet(opcode, 20);
4446 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004447 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004448 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004449 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004450 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4451 return false;
4452 break;
4453 case eEncodingA1:
4454 Rd = Bits32(opcode, 15, 12);
4455 Rn = Bits32(opcode, 19, 16);
4456 setflags = BitIsSet(opcode, 20);
4457 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4458 // TODO: Emulate SUBS PC, LR and related instructions.
4459 if (Rd == 15 && setflags)
4460 return false;
4461 break;
4462 default:
4463 return false;
4464 }
4465
Johnny Chene97c0d52011-02-18 19:32:20 +00004466 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004467 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004468 if (!success)
4469 return false;
4470
4471 uint32_t result = val1 & imm32;
4472
4473 EmulateInstruction::Context context;
4474 context.type = EmulateInstruction::eContextImmediate;
4475 context.SetNoArgs ();
4476
4477 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4478 return false;
4479 }
4480 return true;
4481}
4482
4483// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4484// and writes the result to the destination register. It can optionally update the condition flags
4485// based on the result.
4486bool
4487EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4488{
4489#if 0
4490 // ARM pseudo code...
4491 if ConditionPassed() then
4492 EncodingSpecificOperations();
4493 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4494 result = R[n] AND shifted;
4495 if d == 15 then // Can only occur for ARM encoding
4496 ALUWritePC(result); // setflags is always FALSE here
4497 else
4498 R[d] = result;
4499 if setflags then
4500 APSR.N = result<31>;
4501 APSR.Z = IsZeroBit(result);
4502 APSR.C = carry;
4503 // APSR.V unchanged
4504#endif
4505
4506 bool success = false;
4507 const uint32_t opcode = OpcodeAsUnsigned (&success);
4508 if (!success)
4509 return false;
4510
4511 if (ConditionPassed())
4512 {
4513 uint32_t Rd, Rn, Rm;
4514 ARM_ShifterType shift_t;
4515 uint32_t shift_n; // the shift applied to the value read from Rm
4516 bool setflags;
4517 uint32_t carry;
4518 switch (encoding)
4519 {
4520 case eEncodingT1:
4521 Rd = Rn = Bits32(opcode, 2, 0);
4522 Rm = Bits32(opcode, 5, 3);
4523 setflags = !InITBlock();
4524 shift_t = SRType_LSL;
4525 shift_n = 0;
4526 case eEncodingT2:
4527 Rd = Bits32(opcode, 11, 8);
4528 Rn = Bits32(opcode, 19, 16);
4529 Rm = Bits32(opcode, 3, 0);
4530 setflags = BitIsSet(opcode, 20);
Johnny Chen157b9592011-02-18 21:13:05 +00004531 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 +00004532 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004533 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004534 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004535 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4536 return false;
4537 break;
4538 case eEncodingA1:
4539 Rd = Bits32(opcode, 15, 12);
4540 Rn = Bits32(opcode, 19, 16);
4541 Rm = Bits32(opcode, 3, 0);
4542 setflags = BitIsSet(opcode, 20);
4543 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4544 // TODO: Emulate SUBS PC, LR and related instructions.
4545 if (Rd == 15 && setflags)
4546 return false;
4547 break;
4548 default:
4549 return false;
4550 }
4551
Johnny Chene97c0d52011-02-18 19:32:20 +00004552 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004553 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004554 if (!success)
4555 return false;
4556
4557 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004558 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004559 if (!success)
4560 return false;
4561
4562 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4563 uint32_t result = val1 & shifted;
4564
4565 EmulateInstruction::Context context;
4566 context.type = EmulateInstruction::eContextImmediate;
4567 context.SetNoArgs ();
4568
4569 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4570 return false;
4571 }
4572 return true;
4573}
4574
Caroline Tice4d729c52011-02-18 00:55:53 +00004575// 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 +00004576// 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 +00004577bool
4578EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4579{
4580#if 0
4581 if ConditionPassed() then
4582 EncodingSpecificOperations();
4583 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4584 address = if index then offset_addr else R[n];
4585 data = MemU[address,4];
4586 if wback then R[n] = offset_addr;
4587 if t == 15 then
4588 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4589 elsif UnalignedSupport() || address<1:0> = ’00’ then
4590 R[t] = data;
4591 else // Can only apply before ARMv7
4592 R[t] = ROR(data, 8*UInt(address<1:0>));
4593#endif
4594
4595 bool success = false;
4596 const uint32_t opcode = OpcodeAsUnsigned (&success);
4597 if (!success)
4598 return false;
4599
4600 if (ConditionPassed ())
4601 {
4602 const uint32_t addr_byte_size = GetAddressByteSize();
4603
4604 uint32_t t;
4605 uint32_t n;
4606 uint32_t imm32;
4607 bool index;
4608 bool add;
4609 bool wback;
4610
4611 switch (encoding)
4612 {
4613 case eEncodingA1:
4614 // if Rn == ’1111’ then SEE LDR (literal);
4615 // if P == ’0’ && W == ’1’ then SEE LDRT;
4616 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4617 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4618 t = Bits32 (opcode, 15, 12);
4619 n = Bits32 (opcode, 19, 16);
4620 imm32 = Bits32 (opcode, 11, 0);
4621
4622 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4623 index = BitIsSet (opcode, 24);
4624 add = BitIsSet (opcode, 23);
4625 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4626
4627 // if wback && n == t then UNPREDICTABLE;
4628 if (wback && (n == t))
4629 return false;
4630
4631 break;
4632
4633 default:
4634 return false;
4635 }
4636
4637 addr_t address;
4638 addr_t offset_addr;
4639 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4640 if (!success)
4641 return false;
4642
4643 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4644 if (add)
4645 offset_addr = base_address + imm32;
4646 else
4647 offset_addr = base_address - imm32;
4648
4649 // address = if index then offset_addr else R[n];
4650 if (index)
4651 address = offset_addr;
4652 else
4653 address = base_address;
4654
4655 // data = MemU[address,4];
4656
4657 Register base_reg;
4658 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4659
4660 EmulateInstruction::Context context;
4661 context.type = eContextRegisterLoad;
4662 context.SetRegisterPlusOffset (base_reg, address - base_address);
4663
4664 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4665 if (!success)
4666 return false;
4667
4668 // if wback then R[n] = offset_addr;
4669 if (wback)
4670 {
4671 context.type = eContextAdjustBaseRegister;
4672 context.SetAddress (offset_addr);
4673 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4674 return false;
4675 }
4676
4677 // if t == 15 then
4678 if (t == 15)
4679 {
4680 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4681 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4682 {
4683 // LoadWritePC (data);
4684 context.type = eContextRegisterLoad;
4685 context.SetRegisterPlusOffset (base_reg, address - base_address);
4686 LoadWritePC (context, data);
4687 }
4688 else
4689 return false;
4690 }
4691 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4692 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4693 {
4694 // R[t] = data;
4695 context.type = eContextRegisterLoad;
4696 context.SetRegisterPlusOffset (base_reg, address - base_address);
4697 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4698 return false;
4699 }
4700 // else // Can only apply before ARMv7
4701 else
4702 {
4703 // R[t] = ROR(data, 8*UInt(address<1:0>));
4704 data = ROR (data, Bits32 (address, 1, 0));
4705 context.type = eContextRegisterLoad;
4706 context.SetImmediate (data);
4707 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4708 return false;
4709 }
4710
4711 }
4712 return true;
4713}
4714
Caroline Ticefe479112011-02-18 18:52:37 +00004715// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4716// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4717bool
4718EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4719{
4720#if 0
4721 if ConditionPassed() then
4722 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4723 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4724 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4725 address = if index then offset_addr else R[n];
4726 data = MemU[address,4];
4727 if wback then R[n] = offset_addr;
4728 if t == 15 then
4729 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4730 elsif UnalignedSupport() || address<1:0> = ’00’ then
4731 R[t] = data;
4732 else // Can only apply before ARMv7
4733 if CurrentInstrSet() == InstrSet_ARM then
4734 R[t] = ROR(data, 8*UInt(address<1:0>));
4735 else
4736 R[t] = bits(32) UNKNOWN;
4737#endif
4738
4739 bool success = false;
4740 const uint32_t opcode = OpcodeAsUnsigned (&success);
4741 if (!success)
4742 return false;
4743
4744 if (ConditionPassed ())
4745 {
4746 const uint32_t addr_byte_size = GetAddressByteSize();
4747
4748 uint32_t t;
4749 uint32_t n;
4750 uint32_t m;
4751 bool index;
4752 bool add;
4753 bool wback;
4754 ARM_ShifterType shift_t;
4755 uint32_t shift_n;
4756
4757 switch (encoding)
4758 {
4759 case eEncodingT1:
4760 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4761 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4762 t = Bits32 (opcode, 2, 0);
4763 n = Bits32 (opcode, 5, 3);
4764 m = Bits32 (opcode, 8, 6);
4765
4766 // index = TRUE; add = TRUE; wback = FALSE;
4767 index = true;
4768 add = true;
4769 wback = false;
4770
4771 // (shift_t, shift_n) = (SRType_LSL, 0);
4772 shift_t = SRType_LSL;
4773 shift_n = 0;
4774
4775 break;
4776
4777 case eEncodingT2:
4778 // if Rn == ’1111’ then SEE LDR (literal);
4779 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4780 t = Bits32 (opcode, 15, 12);
4781 n = Bits32 (opcode, 19, 16);
4782 m = Bits32 (opcode, 3, 0);
4783
4784 // index = TRUE; add = TRUE; wback = FALSE;
4785 index = true;
4786 add = true;
4787 wback = false;
4788
4789 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4790 shift_t = SRType_LSL;
4791 shift_n = Bits32 (opcode, 5, 4);
4792
4793 // if BadReg(m) then UNPREDICTABLE;
4794 if (BadReg (m))
4795 return false;
4796
4797 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4798 if ((t == 15) && InITBlock() && !LastInITBlock())
4799 return false;
4800
4801 break;
4802
4803 case eEncodingA1:
4804 {
4805 // if P == ’0’ && W == ’1’ then SEE LDRT;
4806 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4807 t = Bits32 (opcode, 15, 12);
4808 n = Bits32 (opcode, 19, 16);
4809 m = Bits32 (opcode, 3, 0);
4810
4811 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4812 index = BitIsSet (opcode, 24);
4813 add = BitIsSet (opcode, 23);
4814 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4815
4816 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4817 uint32_t type = Bits32 (opcode, 6, 5);
4818 uint32_t imm5 = Bits32 (opcode, 11, 7);
4819 shift_n = DecodeImmShift (type, imm5, shift_t);
4820
4821 // if m == 15 then UNPREDICTABLE;
4822 if (m == 15)
4823 return false;
4824
4825 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4826 if (wback && ((n == 15) || (n == t)))
4827 return false;
4828 }
4829 break;
4830
4831
4832 default:
4833 return false;
4834 }
4835
4836 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4837 if (!success)
4838 return false;
4839
4840 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4841 if (!success)
4842 return false;
4843
4844 addr_t offset_addr;
4845 addr_t address;
4846
4847 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
4848 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
4849
4850 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4851 if (add)
4852 offset_addr = Rn + offset;
4853 else
4854 offset_addr = Rn - offset;
4855
4856 // address = if index then offset_addr else R[n];
4857 if (index)
4858 address = offset_addr;
4859 else
4860 address = Rn;
4861
4862 // data = MemU[address,4];
4863 Register base_reg;
4864 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4865
4866 EmulateInstruction::Context context;
4867 context.type = eContextRegisterLoad;
4868 context.SetRegisterPlusOffset (base_reg, address - Rn);
4869
4870 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4871 if (!success)
4872 return false;
4873
4874 // if wback then R[n] = offset_addr;
4875 if (wback)
4876 {
4877 context.type = eContextAdjustBaseRegister;
4878 context.SetAddress (offset_addr);
4879 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4880 return false;
4881 }
4882
4883 // if t == 15 then
4884 if (t == 15)
4885 {
4886 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4887 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4888 {
4889 context.type = eContextRegisterLoad;
4890 context.SetRegisterPlusOffset (base_reg, address - Rn);
4891 LoadWritePC (context, data);
4892 }
4893 else
4894 return false;
4895 }
4896 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4897 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4898 {
4899 // R[t] = data;
4900 context.type = eContextRegisterLoad;
4901 context.SetRegisterPlusOffset (base_reg, address - Rn);
4902 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4903 return false;
4904 }
4905 else // Can only apply before ARMv7
4906 {
4907 // if CurrentInstrSet() == InstrSet_ARM then
4908 if (CurrentInstrSet () == eModeARM)
4909 {
4910 // R[t] = ROR(data, 8*UInt(address<1:0>));
4911 data = ROR (data, Bits32 (address, 1, 0));
4912 context.type = eContextRegisterLoad;
4913 context.SetImmediate (data);
4914 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4915 return false;
4916 }
4917 else
4918 {
4919 // R[t] = bits(32) UNKNOWN;
4920 WriteBits32Unknown (t);
4921 }
4922 }
4923 }
4924 return true;
4925}
Caroline Tice21b604b2011-02-18 21:06:04 +00004926
4927// LDRB (immediate, Thumb)
4928bool
4929EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
4930{
4931#if 0
4932 if ConditionPassed() then
4933 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4934 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4935 address = if index then offset_addr else R[n];
4936 R[t] = ZeroExtend(MemU[address,1], 32);
4937 if wback then R[n] = offset_addr;
4938#endif
4939
4940 bool success = false;
4941 const uint32_t opcode = OpcodeAsUnsigned (&success);
4942 if (!success)
4943 return false;
4944
4945 if (ConditionPassed ())
4946 {
4947 uint32_t t;
4948 uint32_t n;
4949 uint32_t imm32;
4950 bool index;
4951 bool add;
4952 bool wback;
4953
4954 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4955 switch (encoding)
4956 {
4957 case eEncodingT1:
4958 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4959 t = Bits32 (opcode, 2, 0);
4960 n = Bits32 (opcode, 5, 3);
4961 imm32 = Bits32 (opcode, 10, 6);
4962
4963 // index = TRUE; add = TRUE; wback = FALSE;
4964 index = true;
4965 add = true;
4966 wback= false;
4967
4968 break;
4969
4970 case eEncodingT2:
4971 // if Rt == ’1111’ then SEE PLD;
4972 // if Rn == ’1111’ then SEE LDRB (literal);
4973 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4974 t = Bits32 (opcode, 15, 12);
4975 n = Bits32 (opcode, 19, 16);
4976 imm32 = Bits32 (opcode, 11, 0);
4977
4978 // index = TRUE; add = TRUE; wback = FALSE;
4979 index = true;
4980 add = true;
4981 wback = false;
4982
4983 // if t == 13 then UNPREDICTABLE;
4984 if (t == 13)
4985 return false;
4986
4987 break;
4988
4989 case eEncodingT3:
4990 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
4991 // if Rn == ’1111’ then SEE LDRB (literal);
4992 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
4993 // if P == ’0’ && W == ’0’ then UNDEFINED;
4994 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
4995 return false;
4996
4997 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4998 t = Bits32 (opcode, 15, 12);
4999 n = Bits32 (opcode, 19, 16);
5000 imm32 = Bits32 (opcode, 7, 0);
5001
5002 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5003 index = BitIsSet (opcode, 10);
5004 add = BitIsSet (opcode, 9);
5005 wback = BitIsSet (opcode, 8);
5006
5007 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5008 if (BadReg (t) || (wback && (n == t)))
5009 return false;
5010
5011 break;
5012
5013 default:
5014 return false;
5015 }
5016
5017 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5018 if (!success)
5019 return false;
5020
5021 addr_t address;
5022 addr_t offset_addr;
5023
5024 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5025 if (add)
5026 offset_addr = Rn + imm32;
5027 else
5028 offset_addr = Rn - imm32;
5029
5030 // address = if index then offset_addr else R[n];
5031 if (index)
5032 address = offset_addr;
5033 else
5034 address = Rn;
5035
5036 // R[t] = ZeroExtend(MemU[address,1], 32);
5037 Register base_reg;
5038 Register data_reg;
5039 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5040 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5041
5042 EmulateInstruction::Context context;
5043 context.type = eContextRegisterLoad;
5044 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5045
5046 uint64_t data = MemURead (context, address, 1, 0, &success);
5047 if (!success)
5048 return false;
5049
5050 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5051 return false;
5052
5053 // if wback then R[n] = offset_addr;
5054 if (wback)
5055 {
5056 context.type = eContextAdjustBaseRegister;
5057 context.SetAddress (offset_addr);
5058 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5059 return false;
5060 }
5061 }
5062 return true;
5063}
Caroline Ticef55261f2011-02-18 22:24:22 +00005064
5065// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5066// zero-extends it to form a 32-bit word and writes it to a register.
5067bool
5068EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5069{
5070#if 0
5071 if ConditionPassed() then
5072 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5073 base = Align(PC,4);
5074 address = if add then (base + imm32) else (base - imm32);
5075 R[t] = ZeroExtend(MemU[address,1], 32);
5076#endif
5077
5078 bool success = false;
5079 const uint32_t opcode = OpcodeAsUnsigned (&success);
5080 if (!success)
5081 return false;
5082
5083 if (ConditionPassed ())
5084 {
5085 uint32_t t;
5086 uint32_t imm32;
5087 bool add;
5088 switch (encoding)
5089 {
5090 case eEncodingT1:
5091 // if Rt == ’1111’ then SEE PLD;
5092 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5093 t = Bits32 (opcode, 15, 12);
5094 imm32 = Bits32 (opcode, 11, 0);
5095 add = BitIsSet (opcode, 23);
5096
5097 // if t == 13 then UNPREDICTABLE;
5098 if (t == 13)
5099 return false;
5100
5101 break;
5102
5103 case eEncodingA1:
5104 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5105 t = Bits32 (opcode, 15, 12);
5106 imm32 = Bits32 (opcode, 11, 0);
5107 add = BitIsSet (opcode, 23);
5108
5109 // if t == 15 then UNPREDICTABLE;
5110 if (t == 15)
5111 return false;
5112 break;
5113
5114 default:
5115 return false;
5116 }
5117
5118 // base = Align(PC,4);
5119 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5120 if (!success)
5121 return false;
5122
5123 uint32_t base = AlignPC (pc_val);
5124
5125 addr_t address;
5126 // address = if add then (base + imm32) else (base - imm32);
5127 if (add)
5128 address = base + imm32;
5129 else
5130 address = base - imm32;
5131
5132 // R[t] = ZeroExtend(MemU[address,1], 32);
5133 EmulateInstruction::Context context;
5134 context.type = eContextRelativeBranchImmediate;
5135 context.SetImmediate (address - base);
5136
5137 uint64_t data = MemURead (context, address, 1, 0, &success);
5138 if (!success)
5139 return false;
5140
5141 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5142 return false;
5143 }
5144 return true;
5145}
Caroline Tice30fec122011-02-18 23:52:21 +00005146
5147// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5148// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5149// optionally be shifted.
5150bool
5151EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5152{
5153#if 0
5154 if ConditionPassed() then
5155 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5156 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5157 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5158 address = if index then offset_addr else R[n];
5159 R[t] = ZeroExtend(MemU[address,1],32);
5160 if wback then R[n] = offset_addr;
5161#endif
5162
5163 bool success = false;
5164 const uint32_t opcode = OpcodeAsUnsigned (&success);
5165 if (!success)
5166 return false;
5167
5168 if (ConditionPassed ())
5169 {
5170 uint32_t t;
5171 uint32_t n;
5172 uint32_t m;
5173 bool index;
5174 bool add;
5175 bool wback;
5176 ARM_ShifterType shift_t;
5177 uint32_t shift_n;
5178
5179 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5180 switch (encoding)
5181 {
5182 case eEncodingT1:
5183 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5184 t = Bits32 (opcode, 2, 0);
5185 n = Bits32 (opcode, 5, 3);
5186 m = Bits32 (opcode, 8, 6);
5187
5188 // index = TRUE; add = TRUE; wback = FALSE;
5189 index = true;
5190 add = true;
5191 wback = false;
5192
5193 // (shift_t, shift_n) = (SRType_LSL, 0);
5194 shift_t = SRType_LSL;
5195 shift_n = 0;
5196 break;
5197
5198 case eEncodingT2:
5199 // if Rt == ’1111’ then SEE PLD;
5200 // if Rn == ’1111’ then SEE LDRB (literal);
5201 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5202 t = Bits32 (opcode, 15, 12);
5203 n = Bits32 (opcode, 19, 16);
5204 m = Bits32 (opcode, 3, 0);
5205
5206 // index = TRUE; add = TRUE; wback = FALSE;
5207 index = true;
5208 add = true;
5209 wback = false;
5210
5211 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5212 shift_t = SRType_LSL;
5213 shift_n = Bits32 (opcode, 5, 4);
5214
5215 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5216 if ((t == 13) || BadReg (m))
5217 return false;
5218 break;
5219
5220 case eEncodingA1:
5221 {
5222 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5223 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5224 t = Bits32 (opcode, 15, 12);
5225 n = Bits32 (opcode, 19, 16);
5226 m = Bits32 (opcode, 3, 0);
5227
5228 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5229 index = BitIsSet (opcode, 24);
5230 add = BitIsSet (opcode, 23);
5231 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5232
5233 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5234 uint32_t type = Bits32 (opcode, 6, 5);
5235 uint32_t imm5 = Bits32 (opcode, 11, 7);
5236 shift_n = DecodeImmShift (type, imm5, shift_t);
5237
5238 // if t == 15 || m == 15 then UNPREDICTABLE;
5239 if ((t == 15) || (m == 15))
5240 return false;
5241
5242 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5243 if (wback && ((n == 15) || (n == t)))
5244 return false;
5245 }
5246 break;
5247
5248 default:
5249 return false;
5250 }
5251
5252 addr_t offset_addr;
5253 addr_t address;
5254
5255 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5256 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5257 if (!success)
5258 return false;
5259
5260 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5261
5262 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5263 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5264 if (!success)
5265 return false;
5266
5267 if (add)
5268 offset_addr = Rn + offset;
5269 else
5270 offset_addr = Rn - offset;
5271
5272 // address = if index then offset_addr else R[n];
5273 if (index)
5274 address = offset_addr;
5275 else
5276 address = Rn;
5277
5278 // R[t] = ZeroExtend(MemU[address,1],32);
5279 Register base_reg;
5280 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5281
5282 EmulateInstruction::Context context;
5283 context.type = eContextRegisterLoad;
5284 context.SetRegisterPlusOffset (base_reg, address - Rn);
5285
5286 uint64_t data = MemURead (context, address, 1, 0, &success);
5287 if (!success)
5288 return false;
5289
5290 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5291 return false;
5292
5293 // if wback then R[n] = offset_addr;
5294 if (wback)
5295 {
5296 context.type = eContextAdjustBaseRegister;
5297 context.SetAddress (offset_addr);
5298 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5299 return false;
5300 }
5301 }
5302 return true;
5303}
Caroline Ticefe479112011-02-18 18:52:37 +00005304
Johnny Chen7c5234d2011-02-18 23:41:11 +00005305// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5306// writes the result to the destination register. It can optionally update the condition flags based
5307// on the result.
5308bool
5309EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5310{
5311#if 0
5312 // ARM pseudo code...
5313 if ConditionPassed() then
5314 EncodingSpecificOperations();
5315 result = R[n] OR imm32;
5316 if d == 15 then // Can only occur for ARM encoding
5317 ALUWritePC(result); // setflags is always FALSE here
5318 else
5319 R[d] = result;
5320 if setflags then
5321 APSR.N = result<31>;
5322 APSR.Z = IsZeroBit(result);
5323 APSR.C = carry;
5324 // APSR.V unchanged
5325#endif
5326
5327 bool success = false;
5328 const uint32_t opcode = OpcodeAsUnsigned (&success);
5329 if (!success)
5330 return false;
5331
5332 if (ConditionPassed())
5333 {
5334 uint32_t Rd, Rn;
5335 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5336 bool setflags;
5337 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5338 switch (encoding)
5339 {
5340 case eEncodingT1:
5341 Rd = Bits32(opcode, 11, 8);
5342 Rn = Bits32(opcode, 19, 16);
5343 setflags = BitIsSet(opcode, 20);
5344 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5345 // if Rn == ‘1111’ then SEE MOV (immediate);
5346 if (Rn == 15)
5347 return EmulateMOVRdImm(eEncodingT2);
5348 if (BadReg(Rd) || Rn == 13)
5349 return false;
5350 break;
5351 case eEncodingA1:
5352 Rd = Bits32(opcode, 15, 12);
5353 Rn = Bits32(opcode, 19, 16);
5354 setflags = BitIsSet(opcode, 20);
5355 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5356 // TODO: Emulate SUBS PC, LR and related instructions.
5357 if (Rd == 15 && setflags)
5358 return false;
5359 break;
5360 default:
5361 return false;
5362 }
5363
5364 // Read the first operand.
5365 uint32_t val1 = ReadCoreReg(Rn, &success);
5366 if (!success)
5367 return false;
5368
5369 uint32_t result = val1 | imm32;
5370
5371 EmulateInstruction::Context context;
5372 context.type = EmulateInstruction::eContextImmediate;
5373 context.SetNoArgs ();
5374
5375 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5376 return false;
5377 }
5378 return true;
5379}
5380
5381// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5382// value, and writes the result to the destination register. It can optionally update the condition flags based
5383// on the result.
5384bool
5385EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5386{
5387#if 0
5388 // ARM pseudo code...
5389 if ConditionPassed() then
5390 EncodingSpecificOperations();
5391 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5392 result = R[n] OR shifted;
5393 if d == 15 then // Can only occur for ARM encoding
5394 ALUWritePC(result); // setflags is always FALSE here
5395 else
5396 R[d] = result;
5397 if setflags then
5398 APSR.N = result<31>;
5399 APSR.Z = IsZeroBit(result);
5400 APSR.C = carry;
5401 // APSR.V unchanged
5402#endif
5403
5404 bool success = false;
5405 const uint32_t opcode = OpcodeAsUnsigned (&success);
5406 if (!success)
5407 return false;
5408
5409 if (ConditionPassed())
5410 {
5411 uint32_t Rd, Rn, Rm;
5412 ARM_ShifterType shift_t;
5413 uint32_t shift_n; // the shift applied to the value read from Rm
5414 bool setflags;
5415 uint32_t carry;
5416 switch (encoding)
5417 {
5418 case eEncodingT1:
5419 Rd = Rn = Bits32(opcode, 2, 0);
5420 Rm = Bits32(opcode, 5, 3);
5421 setflags = !InITBlock();
5422 shift_t = SRType_LSL;
5423 shift_n = 0;
5424 case eEncodingT2:
5425 Rd = Bits32(opcode, 11, 8);
5426 Rn = Bits32(opcode, 19, 16);
5427 Rm = Bits32(opcode, 3, 0);
5428 setflags = BitIsSet(opcode, 20);
5429 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5430 // if Rn == ‘1111’ then SEE MOV (register);
5431 if (Rn == 15)
5432 return EmulateMOVRdRm(eEncodingT3);
5433 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5434 return false;
5435 break;
5436 case eEncodingA1:
5437 Rd = Bits32(opcode, 15, 12);
5438 Rn = Bits32(opcode, 19, 16);
5439 Rm = Bits32(opcode, 3, 0);
5440 setflags = BitIsSet(opcode, 20);
5441 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5442 // TODO: Emulate SUBS PC, LR and related instructions.
5443 if (Rd == 15 && setflags)
5444 return false;
5445 break;
5446 default:
5447 return false;
5448 }
5449
5450 // Read the first operand.
5451 uint32_t val1 = ReadCoreReg(Rn, &success);
5452 if (!success)
5453 return false;
5454
5455 // Read the second operand.
5456 uint32_t val2 = ReadCoreReg(Rm, &success);
5457 if (!success)
5458 return false;
5459
5460 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5461 uint32_t result = val1 & shifted;
5462
5463 EmulateInstruction::Context context;
5464 context.type = EmulateInstruction::eContextImmediate;
5465 context.SetNoArgs ();
5466
5467 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5468 return false;
5469 }
5470 return true;
5471}
5472
Johnny Chende3cce32011-02-21 21:24:49 +00005473// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
5474// It updates the condition flags based on the result, and discards the result.
5475bool
5476EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
5477{
5478#if 0
5479 // ARM pseudo code...
5480 if ConditionPassed() then
5481 EncodingSpecificOperations();
5482 result = R[n] AND imm32;
5483 APSR.N = result<31>;
5484 APSR.Z = IsZeroBit(result);
5485 APSR.C = carry;
5486 // APSR.V unchanged
5487#endif
5488
5489 bool success = false;
5490 const uint32_t opcode = OpcodeAsUnsigned (&success);
5491 if (!success)
5492 return false;
5493
5494 if (ConditionPassed())
5495 {
5496 uint32_t Rn;
5497 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5498 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5499 switch (encoding)
5500 {
5501 case eEncodingT1:
5502 Rn = Bits32(opcode, 19, 16);
5503 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5504 if (BadReg(Rn))
5505 return false;
5506 break;
5507 case eEncodingA1:
5508 Rn = Bits32(opcode, 19, 16);
5509 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5510 break;
5511 default:
5512 return false;
5513 }
5514
5515 // Read the first operand.
5516 uint32_t val1 = ReadCoreReg(Rn, &success);
5517 if (!success)
5518 return false;
5519
5520 uint32_t result = val1 & imm32;
5521
5522 EmulateInstruction::Context context;
5523 context.type = EmulateInstruction::eContextImmediate;
5524 context.SetNoArgs ();
5525
5526 if (!WriteFlags(context, result, carry))
5527 return false;
5528 }
5529 return true;
5530}
5531
5532// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
5533// It updates the condition flags based on the result, and discards the result.
5534bool
5535EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
5536{
5537#if 0
5538 // ARM pseudo code...
5539 if ConditionPassed() then
5540 EncodingSpecificOperations();
5541 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5542 result = R[n] AND shifted;
5543 APSR.N = result<31>;
5544 APSR.Z = IsZeroBit(result);
5545 APSR.C = carry;
5546 // APSR.V unchanged
5547#endif
5548
5549 bool success = false;
5550 const uint32_t opcode = OpcodeAsUnsigned (&success);
5551 if (!success)
5552 return false;
5553
5554 if (ConditionPassed())
5555 {
5556 uint32_t Rn, Rm;
5557 ARM_ShifterType shift_t;
5558 uint32_t shift_n; // the shift applied to the value read from Rm
5559 uint32_t carry;
5560 switch (encoding)
5561 {
5562 case eEncodingT1:
5563 Rn = Bits32(opcode, 2, 0);
5564 Rm = Bits32(opcode, 5, 3);
5565 shift_t = SRType_LSL;
5566 shift_n = 0;
5567 case eEncodingT2:
5568 Rn = Bits32(opcode, 19, 16);
5569 Rm = Bits32(opcode, 3, 0);
5570 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5571 if (BadReg(Rn) || BadReg(Rm))
5572 return false;
5573 break;
5574 case eEncodingA1:
5575 Rn = Bits32(opcode, 19, 16);
5576 Rm = Bits32(opcode, 3, 0);
5577 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5578 break;
5579 default:
5580 return false;
5581 }
5582
5583 // Read the first operand.
5584 uint32_t val1 = ReadCoreReg(Rn, &success);
5585 if (!success)
5586 return false;
5587
5588 // Read the second operand.
5589 uint32_t val2 = ReadCoreReg(Rm, &success);
5590 if (!success)
5591 return false;
5592
5593 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5594 uint32_t result = val1 & shifted;
5595
5596 EmulateInstruction::Context context;
5597 context.type = EmulateInstruction::eContextImmediate;
5598 context.SetNoArgs ();
5599
5600 if (!WriteFlags(context, result, carry))
5601 return false;
5602 }
5603 return true;
5604}
5605
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005606EmulateInstructionARM::ARMOpcode*
5607EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00005608{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005609 static ARMOpcode
5610 g_arm_opcodes[] =
5611 {
5612 //----------------------------------------------------------------------
5613 // Prologue instructions
5614 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00005615
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005616 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005617 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5618 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00005619
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005620 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005621 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005622 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00005623 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00005624 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
5625 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005626 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00005627
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005628 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005629 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00005630
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005631 // push one register
5632 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00005633 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00005634
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005635 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00005636 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5637 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00005638
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005639 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00005640 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005641 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00005642
Johnny Chen9f687722011-02-18 00:02:28 +00005643 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5644 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00005645 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005646 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
5647
5648 //----------------------------------------------------------------------
5649 // Supervisor Call (previously Software Interrupt)
5650 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005651 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
5652
5653 //----------------------------------------------------------------------
5654 // Branch instructions
5655 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005656 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00005657 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
5658 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5659 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5660 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005661 // for example, "bx lr"
5662 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005663
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005664 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00005665 // Data-processing instructions
5666 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005667 // adc (immediate)
5668 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
5669 // adc (register)
5670 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005671 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005672 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005673 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005674 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005675 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005676 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005677 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005678 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005679 // orr (immediate)
5680 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
5681 // orr (register)
5682 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00005683 // tst (immediate)
5684 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
5685 // tst (register)
5686 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
5687
5688
Johnny Chen28070c32011-02-12 01:27:26 +00005689 // move bitwise not
Johnny Chen157b9592011-02-18 21:13:05 +00005690 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005691 // asr (immediate)
5692 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005693 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00005694 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005695 // lsl (immediate)
5696 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
5697 // lsl (register)
5698 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
5699 // lsr (immediate)
5700 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
5701 // lsr (register)
5702 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005703 // rrx is a special case encoding of ror (immediate)
5704 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
5705 // ror (immediate)
5706 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
5707 // ror (register)
5708 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005709
5710 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005711 // Load instructions
5712 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00005713 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00005714 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00005715 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00005716 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00005717 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00005718 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00005719 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
5720 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00005721
5722 //----------------------------------------------------------------------
5723 // Store instructions
5724 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00005725 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005726 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00005727 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00005728 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
5729 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00005730
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005731
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005732 };
5733 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
5734
5735 for (size_t i=0; i<k_num_arm_opcodes; ++i)
5736 {
5737 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
5738 return &g_arm_opcodes[i];
5739 }
5740 return NULL;
5741}
Greg Clayton64c84432011-01-21 22:02:52 +00005742
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005743
5744EmulateInstructionARM::ARMOpcode*
5745EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00005746{
Johnny Chenfdd179e2011-01-31 20:09:28 +00005747
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005748 static ARMOpcode
5749 g_thumb_opcodes[] =
5750 {
5751 //----------------------------------------------------------------------
5752 // Prologue instructions
5753 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00005754
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005755 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005756 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5757 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
5758 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00005759
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005760 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005761 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005762 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00005763 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005764 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00005765 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00005766
Johnny Chen864a8e82011-02-18 00:07:39 +00005767 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00005768 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00005769
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005770 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005771 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
5772 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
5773 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
5774 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005775
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005776 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00005777 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5778 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005779
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005780 //----------------------------------------------------------------------
5781 // Epilogue instructions
5782 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00005783
Johnny Chen864a8e82011-02-18 00:07:39 +00005784 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00005785 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5786 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
5787 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00005788 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
5789 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005790
5791 //----------------------------------------------------------------------
5792 // Supervisor Call (previously Software Interrupt)
5793 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00005794 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
5795
5796 //----------------------------------------------------------------------
5797 // If Then makes up to four following instructions conditional.
5798 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005799 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
5800
5801 //----------------------------------------------------------------------
5802 // Branch instructions
5803 //----------------------------------------------------------------------
5804 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
5805 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
5806 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00005807 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005808 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00005809 // J1 == J2 == 1
5810 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5811 // J1 == J2 == 1
5812 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5813 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005814 // for example, "bx lr"
5815 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00005816 // compare and branch
5817 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00005818 // table branch byte
5819 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
5820 // table branch halfword
5821 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005822
5823 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00005824 // Data-processing instructions
5825 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005826 // adc (immediate)
5827 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
5828 // adc (register)
5829 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
5830 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
5831 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00005832 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005833 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00005834 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005835 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005836 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005837 // and (register)
5838 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
5839 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005840 // orr (immediate)
5841 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
5842 // orr (register)
5843 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
5844 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00005845 // tst (immediate)
5846 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tsts}<c> <Rn>, #<const>"},
5847 // tst (register)
5848 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
5849 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
5850
Johnny Chen7c5234d2011-02-18 23:41:11 +00005851
Johnny Chen338bf542011-02-10 19:29:03 +00005852 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00005853 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00005854 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00005855 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005856 // mov{s}<c>.w <Rd>, <Rm>
5857 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00005858 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005859 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
5860 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005861 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005862 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00005863 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005864 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005865 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005866 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005867 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005868 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005869 // asr (immediate)
5870 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00005871 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00005872 // asr (register)
5873 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
5874 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005875 // lsl (immediate)
5876 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
5877 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
5878 // lsl (register)
5879 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
5880 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
5881 // lsr (immediate)
5882 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
5883 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
5884 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00005885 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005886 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005887 // rrx is a special case encoding of ror (immediate)
5888 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
5889 // ror (immediate)
5890 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
5891 // ror (register)
5892 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
5893 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005894
5895 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005896 // Load instructions
5897 //----------------------------------------------------------------------
5898 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00005899 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00005900 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00005901 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
5902 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00005903 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00005904 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
5905 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00005906 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
5907 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
5908 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00005909 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00005910 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
5911 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00005912
5913 //----------------------------------------------------------------------
5914 // Store instructions
5915 //----------------------------------------------------------------------
5916 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005917 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00005918 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00005919 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
5920 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
5921 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
5922 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
5923 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
5924 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
5925 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
5926 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
5927 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005928 };
5929
5930 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
5931 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
5932 {
5933 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
5934 return &g_thumb_opcodes[i];
5935 }
5936 return NULL;
5937}
Greg Clayton64c84432011-01-21 22:02:52 +00005938
Greg Clayton31e2a382011-01-30 20:03:56 +00005939bool
Greg Clayton395fc332011-02-15 21:59:32 +00005940EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00005941{
5942 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00005943 const char *arch_cstr = arch.AsCString ();
5944 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00005945 {
Greg Clayton395fc332011-02-15 21:59:32 +00005946 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
5947 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
5948 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
5949 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
5950 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
5951 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
5952 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
5953 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
5954 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
5955 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00005956 }
5957 return m_arm_isa != 0;
5958}
5959
5960
Greg Clayton64c84432011-01-21 22:02:52 +00005961bool
5962EmulateInstructionARM::ReadInstruction ()
5963{
5964 bool success = false;
5965 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
5966 if (success)
5967 {
5968 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
5969 if (success)
5970 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00005971 Context read_inst_context;
5972 read_inst_context.type = eContextReadOpcode;
5973 read_inst_context.SetNoArgs ();
5974
Greg Clayton64c84432011-01-21 22:02:52 +00005975 if (m_inst_cpsr & MASK_CPSR_T)
5976 {
5977 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005978 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005979
5980 if (success)
5981 {
5982 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
5983 {
5984 m_inst.opcode_type = eOpcode16;
5985 m_inst.opcode.inst16 = thumb_opcode;
5986 }
5987 else
5988 {
5989 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005990 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005991 }
5992 }
5993 }
5994 else
5995 {
5996 m_inst_mode = eModeARM;
5997 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005998 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005999 }
6000 }
6001 }
6002 if (!success)
6003 {
6004 m_inst_mode = eModeInvalid;
6005 m_inst_pc = LLDB_INVALID_ADDRESS;
6006 }
6007 return success;
6008}
6009
Johnny Chenee9b1f72011-02-09 01:00:31 +00006010uint32_t
6011EmulateInstructionARM::ArchVersion ()
6012{
6013 return m_arm_isa;
6014}
6015
Greg Clayton64c84432011-01-21 22:02:52 +00006016bool
6017EmulateInstructionARM::ConditionPassed ()
6018{
6019 if (m_inst_cpsr == 0)
6020 return false;
6021
6022 const uint32_t cond = CurrentCond ();
6023
6024 if (cond == UINT32_MAX)
6025 return false;
6026
6027 bool result = false;
6028 switch (UnsignedBits(cond, 3, 1))
6029 {
6030 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
6031 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
6032 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
6033 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
6034 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
6035 case 5:
6036 {
6037 bool n = (m_inst_cpsr & MASK_CPSR_N);
6038 bool v = (m_inst_cpsr & MASK_CPSR_V);
6039 result = n == v;
6040 }
6041 break;
6042 case 6:
6043 {
6044 bool n = (m_inst_cpsr & MASK_CPSR_N);
6045 bool v = (m_inst_cpsr & MASK_CPSR_V);
6046 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
6047 }
6048 break;
6049 case 7:
6050 result = true;
6051 break;
6052 }
6053
6054 if (cond & 1)
6055 result = !result;
6056 return result;
6057}
6058
Johnny Chen9ee056b2011-02-08 00:06:35 +00006059uint32_t
6060EmulateInstructionARM::CurrentCond ()
6061{
6062 switch (m_inst_mode)
6063 {
6064 default:
6065 case eModeInvalid:
6066 break;
6067
6068 case eModeARM:
6069 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
6070
6071 case eModeThumb:
6072 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
6073 // 'cond' field of the encoding.
6074 if (m_inst.opcode_type == eOpcode16 &&
6075 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
6076 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
6077 {
6078 return Bits32(m_inst.opcode.inst16, 11, 7);
6079 }
6080 else if (m_inst.opcode_type == eOpcode32 &&
6081 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
6082 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
6083 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
6084 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
6085 {
6086 return Bits32(m_inst.opcode.inst32, 25, 22);
6087 }
6088
6089 return m_it_session.GetCond();
6090 }
6091 return UINT32_MAX; // Return invalid value
6092}
6093
Johnny Chen9ee056b2011-02-08 00:06:35 +00006094bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00006095EmulateInstructionARM::InITBlock()
6096{
6097 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
6098}
6099
6100bool
6101EmulateInstructionARM::LastInITBlock()
6102{
6103 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
6104}
6105
6106bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00006107EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
6108{
6109 addr_t target;
6110
Johnny Chenee9b1f72011-02-09 01:00:31 +00006111 // Check the current instruction set.
6112 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006113 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006114 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00006115 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006116
Johnny Chen9ee056b2011-02-08 00:06:35 +00006117 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006118 return false;
6119
6120 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006121}
6122
6123// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
6124bool
Johnny Chen668b4512011-02-15 21:08:58 +00006125EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006126{
6127 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00006128 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
6129 // we want to record it and issue a WriteRegister callback so the clients
6130 // can track the mode changes accordingly.
6131 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006132
6133 if (BitIsSet(addr, 0))
6134 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006135 if (CurrentInstrSet() != eModeThumb)
6136 {
6137 SelectInstrSet(eModeThumb);
6138 cpsr_changed = true;
6139 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006140 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00006141 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006142 }
6143 else if (BitIsClear(addr, 1))
6144 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006145 if (CurrentInstrSet() != eModeARM)
6146 {
6147 SelectInstrSet(eModeARM);
6148 cpsr_changed = true;
6149 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006150 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00006151 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006152 }
6153 else
6154 return false; // address<1:0> == '10' => UNPREDICTABLE
6155
Johnny Chen0f309db2011-02-09 19:11:32 +00006156 if (cpsr_changed)
6157 {
Johnny Chen558133b2011-02-09 23:59:17 +00006158 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00006159 return false;
6160 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006161 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006162 return false;
6163
6164 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006165}
Greg Clayton64c84432011-01-21 22:02:52 +00006166
Johnny Chenee9b1f72011-02-09 01:00:31 +00006167// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
6168bool
Johnny Chen668b4512011-02-15 21:08:58 +00006169EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00006170{
6171 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00006172 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00006173 else
6174 return BranchWritePC((const Context)context, addr);
6175}
6176
Johnny Chen26863dc2011-02-09 23:43:29 +00006177// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
6178bool
Johnny Chen668b4512011-02-15 21:08:58 +00006179EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00006180{
6181 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00006182 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00006183 else
6184 return BranchWritePC((const Context)context, addr);
6185}
6186
Johnny Chenee9b1f72011-02-09 01:00:31 +00006187EmulateInstructionARM::Mode
6188EmulateInstructionARM::CurrentInstrSet ()
6189{
6190 return m_inst_mode;
6191}
6192
6193// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00006194// ReadInstruction() is performed. This function has a side effect of updating
6195// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00006196bool
6197EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
6198{
Johnny Chen558133b2011-02-09 23:59:17 +00006199 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006200 switch (arm_or_thumb)
6201 {
6202 default:
6203 return false;
6204 eModeARM:
6205 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006206 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006207 break;
6208 eModeThumb:
6209 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006210 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006211 break;
6212 }
6213 return true;
6214}
6215
Johnny Chenef21b592011-02-10 01:52:38 +00006216// This function returns TRUE if the processor currently provides support for
6217// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
6218// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
6219bool
6220EmulateInstructionARM::UnalignedSupport()
6221{
6222 return (ArchVersion() >= ARMv7);
6223}
6224
Johnny Chenbf6ad172011-02-11 01:29:53 +00006225// The main addition and subtraction instructions can produce status information
6226// about both unsigned carry and signed overflow conditions. This status
6227// information can be used to synthesize multi-word additions and subtractions.
6228EmulateInstructionARM::AddWithCarryResult
6229EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
6230{
6231 uint32_t result;
6232 uint8_t carry_out;
6233 uint8_t overflow;
6234
6235 uint64_t unsigned_sum = x + y + carry_in;
6236 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
6237
6238 result = UnsignedBits(unsigned_sum, 31, 0);
6239 carry_out = (result == unsigned_sum ? 0 : 1);
6240 overflow = ((int32_t)result == signed_sum ? 0 : 1);
6241
6242 AddWithCarryResult res = { result, carry_out, overflow };
6243 return res;
6244}
6245
Johnny Chen157b9592011-02-18 21:13:05 +00006246uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00006247EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00006248{
Johnny Chene39f22d2011-02-19 01:36:13 +00006249 uint32_t reg_kind, reg_num;
6250 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00006251 {
Johnny Chene39f22d2011-02-19 01:36:13 +00006252 case SP_REG:
6253 reg_kind = eRegisterKindGeneric;
6254 reg_num = LLDB_REGNUM_GENERIC_SP;
6255 break;
6256 case LR_REG:
6257 reg_kind = eRegisterKindGeneric;
6258 reg_num = LLDB_REGNUM_GENERIC_RA;
6259 break;
6260 case PC_REG:
6261 reg_kind = eRegisterKindGeneric;
6262 reg_num = LLDB_REGNUM_GENERIC_PC;
6263 break;
6264 default:
6265 if (0 <= num && num < SP_REG)
6266 {
6267 reg_kind = eRegisterKindDWARF;
6268 reg_num = dwarf_r0 + num;
6269 }
Johnny Chen157b9592011-02-18 21:13:05 +00006270 else
Johnny Chene39f22d2011-02-19 01:36:13 +00006271 {
6272 assert(0 && "Invalid register number");
6273 *success = false;
6274 return ~0u;
6275 }
6276 break;
Johnny Chen157b9592011-02-18 21:13:05 +00006277 }
Johnny Chene39f22d2011-02-19 01:36:13 +00006278
6279 // Read our register.
6280 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
6281
6282 // When executing an ARM instruction , PC reads as the address of the current
6283 // instruction plus 8.
6284 // When executing a Thumb instruction , PC reads as the address of the current
6285 // instruction plus 4.
6286 if (num == 15)
6287 {
6288 if (CurrentInstrSet() == eModeARM)
6289 val += 8;
6290 else
6291 val += 4;
6292 }
Johnny Chen157b9592011-02-18 21:13:05 +00006293
6294 return val;
6295}
6296
Johnny Chenca67d1c2011-02-17 01:35:27 +00006297// Write the result to the ARM core register Rd, and optionally update the
6298// condition flags based on the result.
6299//
6300// This helper method tries to encapsulate the following pseudocode from the
6301// ARM Architecture Reference Manual:
6302//
6303// if d == 15 then // Can only occur for encoding A1
6304// ALUWritePC(result); // setflags is always FALSE here
6305// else
6306// R[d] = result;
6307// if setflags then
6308// APSR.N = result<31>;
6309// APSR.Z = IsZeroBit(result);
6310// APSR.C = carry;
6311// // APSR.V unchanged
6312//
6313// In the above case, the API client does not pass in the overflow arg, which
6314// defaults to ~0u.
6315bool
Johnny Chen10530c22011-02-17 22:37:12 +00006316EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
6317 const uint32_t result,
6318 const uint32_t Rd,
6319 bool setflags,
6320 const uint32_t carry,
6321 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00006322{
6323 if (Rd == 15)
6324 {
6325 if (!ALUWritePC (context, result))
6326 return false;
6327 }
6328 else
6329 {
6330 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
6331 return false;
6332 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00006333 return WriteFlags (context, result, carry, overflow);
6334 }
6335 return true;
6336}
6337
6338// This helper method tries to encapsulate the following pseudocode from the
6339// ARM Architecture Reference Manual:
6340//
6341// APSR.N = result<31>;
6342// APSR.Z = IsZeroBit(result);
6343// APSR.C = carry;
6344// APSR.V = overflow
6345//
6346// Default arguments can be specified for carry and overflow parameters, which means
6347// not to update the respective flags.
6348bool
6349EmulateInstructionARM::WriteFlags (Context &context,
6350 const uint32_t result,
6351 const uint32_t carry,
6352 const uint32_t overflow)
6353{
6354 m_new_inst_cpsr = m_inst_cpsr;
6355 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
6356 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
6357 if (carry != ~0u)
6358 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
6359 if (overflow != ~0u)
6360 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
6361 if (m_new_inst_cpsr != m_inst_cpsr)
6362 {
6363 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
6364 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00006365 }
6366 return true;
6367}
6368
Greg Clayton64c84432011-01-21 22:02:52 +00006369bool
6370EmulateInstructionARM::EvaluateInstruction ()
6371{
Johnny Chenc315f862011-02-05 00:46:10 +00006372 // Advance the ITSTATE bits to their values for the next instruction.
6373 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
6374 m_it_session.ITAdvance();
6375
Greg Clayton64c84432011-01-21 22:02:52 +00006376 return false;
6377}