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