blob: 2669b0ee3d64d3cb55f89825a2334bfc739288cd [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);
Johnny Chen3dd06052011-02-22 21:17:52 +0000832 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000833 // 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);
Johnny Chen3dd06052011-02-22 21:17:52 +0000840 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000841 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);
Johnny Chen3dd06052011-02-22 21:17:52 +00002131 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002132 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002133 default:
2134 return false;
2135 }
2136
Johnny Chen26863dc2011-02-09 23:43:29 +00002137 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002138 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002139 if (!success)
2140 return false;
2141
2142 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002143 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002144 if (!success)
2145 return false;
2146
Johnny Chene97c0d52011-02-18 19:32:20 +00002147 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002148 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002149
2150 EmulateInstruction::Context context;
2151 context.type = EmulateInstruction::eContextImmediate;
2152 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002153
Johnny Chen10530c22011-02-17 22:37:12 +00002154 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002155 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002156 }
2157 return true;
2158}
2159
Johnny Chen34075cb2011-02-22 01:56:31 +00002160// Compare Negative (immediate) adds a register value and an immediate value.
2161// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002162bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002163EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2164{
2165#if 0
2166 // ARM pseudo code...
2167 if ConditionPassed() then
2168 EncodingSpecificOperations();
2169 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2170 APSR.N = result<31>;
2171 APSR.Z = IsZeroBit(result);
2172 APSR.C = carry;
2173 APSR.V = overflow;
2174#endif
2175
2176 bool success = false;
2177 const uint32_t opcode = OpcodeAsUnsigned (&success);
2178 if (!success)
2179 return false;
2180
2181 uint32_t Rn; // the first operand
2182 uint32_t imm32; // the immediate value to be compared with
2183 switch (encoding) {
2184 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002185 Rn = Bits32(opcode, 19, 16);
2186 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2187 if (Rn == 15)
2188 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002189 case eEncodingA1:
2190 Rn = Bits32(opcode, 19, 16);
2191 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2192 break;
2193 default:
2194 return false;
2195 }
2196 // Read the register value from the operand register Rn.
2197 uint32_t reg_val = ReadCoreReg(Rn, &success);
2198 if (!success)
2199 return false;
2200
Johnny Chen078fbc62011-02-22 19:48:22 +00002201 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002202
2203 EmulateInstruction::Context context;
2204 context.type = EmulateInstruction::eContextImmediate;
2205 context.SetNoArgs ();
2206 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2207 return false;
2208
2209 return true;
2210}
2211
2212// Compare Negative (register) adds a register value and an optionally-shifted register value.
2213// It updates the condition flags based on the result, and discards the result.
2214bool
2215EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2216{
2217#if 0
2218 // ARM pseudo code...
2219 if ConditionPassed() then
2220 EncodingSpecificOperations();
2221 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2222 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2223 APSR.N = result<31>;
2224 APSR.Z = IsZeroBit(result);
2225 APSR.C = carry;
2226 APSR.V = overflow;
2227#endif
2228
2229 bool success = false;
2230 const uint32_t opcode = OpcodeAsUnsigned (&success);
2231 if (!success)
2232 return false;
2233
2234 uint32_t Rn; // the first operand
2235 uint32_t Rm; // the second operand
2236 ARM_ShifterType shift_t;
2237 uint32_t shift_n; // the shift applied to the value read from Rm
2238 switch (encoding) {
2239 case eEncodingT1:
2240 Rn = Bits32(opcode, 2, 0);
2241 Rm = Bits32(opcode, 5, 3);
2242 shift_t = SRType_LSL;
2243 shift_n = 0;
2244 break;
2245 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002246 Rn = Bits32(opcode, 19, 16);
2247 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002248 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002249 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2250 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002251 return false;
2252 break;
2253 case eEncodingA1:
2254 Rn = Bits32(opcode, 19, 16);
2255 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002256 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen34075cb2011-02-22 01:56:31 +00002257 default:
2258 return false;
2259 }
2260 // Read the register value from register Rn.
2261 uint32_t val1 = ReadCoreReg(Rn, &success);
2262 if (!success)
2263 return false;
2264
2265 // Read the register value from register Rm.
2266 uint32_t val2 = ReadCoreReg(Rm, &success);
2267 if (!success)
2268 return false;
2269
2270 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002271 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002272
2273 EmulateInstruction::Context context;
2274 context.type = EmulateInstruction::eContextImmediate;
2275 context.SetNoArgs();
2276 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2277 return false;
2278
2279 return true;
2280}
2281
2282// Compare (immediate) subtracts an immediate value from a register value.
2283// It updates the condition flags based on the result, and discards the result.
2284bool
2285EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002286{
2287#if 0
2288 // ARM pseudo code...
2289 if ConditionPassed() then
2290 EncodingSpecificOperations();
2291 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2292 APSR.N = result<31>;
2293 APSR.Z = IsZeroBit(result);
2294 APSR.C = carry;
2295 APSR.V = overflow;
2296#endif
2297
2298 bool success = false;
2299 const uint32_t opcode = OpcodeAsUnsigned (&success);
2300 if (!success)
2301 return false;
2302
2303 uint32_t Rn; // the first operand
2304 uint32_t imm32; // the immediate value to be compared with
2305 switch (encoding) {
2306 case eEncodingT1:
2307 Rn = Bits32(opcode, 10, 8);
2308 imm32 = Bits32(opcode, 7, 0);
Johnny Chen078fbc62011-02-22 19:48:22 +00002309 case eEncodingT2:
2310 Rn = Bits32(opcode, 19, 16);
2311 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2312 if (Rn == 15)
2313 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002314 case eEncodingA1:
2315 Rn = Bits32(opcode, 19, 16);
2316 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002317 break;
2318 default:
2319 return false;
2320 }
2321 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002322 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002323 if (!success)
2324 return false;
2325
Johnny Chen10530c22011-02-17 22:37:12 +00002326 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2327
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002328 EmulateInstruction::Context context;
2329 context.type = EmulateInstruction::eContextImmediate;
2330 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002331 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2332 return false;
2333
Johnny Chend4dc4442011-02-11 02:02:56 +00002334 return true;
2335}
2336
Johnny Chen34075cb2011-02-22 01:56:31 +00002337// Compare (register) subtracts an optionally-shifted register value from a register value.
2338// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002339bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002340EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002341{
2342#if 0
2343 // ARM pseudo code...
2344 if ConditionPassed() then
2345 EncodingSpecificOperations();
2346 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2347 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2348 APSR.N = result<31>;
2349 APSR.Z = IsZeroBit(result);
2350 APSR.C = carry;
2351 APSR.V = overflow;
2352#endif
2353
2354 bool success = false;
2355 const uint32_t opcode = OpcodeAsUnsigned (&success);
2356 if (!success)
2357 return false;
2358
2359 uint32_t Rn; // the first operand
2360 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002361 ARM_ShifterType shift_t;
2362 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002363 switch (encoding) {
2364 case eEncodingT1:
2365 Rn = Bits32(opcode, 2, 0);
2366 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002367 shift_t = SRType_LSL;
2368 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002369 break;
2370 case eEncodingT2:
2371 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2372 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002373 shift_t = SRType_LSL;
2374 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002375 if (Rn < 8 && Rm < 8)
2376 return false;
2377 if (Rn == 15 || Rm == 15)
2378 return false;
2379 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002380 case eEncodingA1:
2381 Rn = Bits32(opcode, 19, 16);
2382 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002383 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene4a4d302011-02-11 21:53:58 +00002384 default:
2385 return false;
2386 }
2387 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002388 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002389 if (!success)
2390 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002391
Johnny Chene4a4d302011-02-11 21:53:58 +00002392 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002393 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002394 if (!success)
2395 return false;
2396
Johnny Chen34075cb2011-02-22 01:56:31 +00002397 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2398 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002399
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002400 EmulateInstruction::Context context;
2401 context.type = EmulateInstruction::eContextImmediate;
2402 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002403 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2404 return false;
2405
Johnny Chene4a4d302011-02-11 21:53:58 +00002406 return true;
2407}
2408
Johnny Chen82f16aa2011-02-15 20:10:55 +00002409// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2410// shifting in copies of its sign bit, and writes the result to the destination register. It can
2411// optionally update the condition flags based on the result.
2412bool
2413EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2414{
2415#if 0
2416 // ARM pseudo code...
2417 if ConditionPassed() then
2418 EncodingSpecificOperations();
2419 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2420 if d == 15 then // Can only occur for ARM encoding
2421 ALUWritePC(result); // setflags is always FALSE here
2422 else
2423 R[d] = result;
2424 if setflags then
2425 APSR.N = result<31>;
2426 APSR.Z = IsZeroBit(result);
2427 APSR.C = carry;
2428 // APSR.V unchanged
2429#endif
2430
Johnny Chen41a0a152011-02-16 01:27:54 +00002431 return EmulateShiftImm(encoding, SRType_ASR);
2432}
2433
2434// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2435// shifting in copies of its sign bit, and writes the result to the destination register.
2436// The variable number of bits is read from the bottom byte of a register. It can optionally update
2437// the condition flags based on the result.
2438bool
2439EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2440{
2441#if 0
2442 // ARM pseudo code...
2443 if ConditionPassed() then
2444 EncodingSpecificOperations();
2445 shift_n = UInt(R[m]<7:0>);
2446 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2447 R[d] = result;
2448 if setflags then
2449 APSR.N = result<31>;
2450 APSR.Z = IsZeroBit(result);
2451 APSR.C = carry;
2452 // APSR.V unchanged
2453#endif
2454
2455 return EmulateShiftReg(encoding, SRType_ASR);
2456}
2457
2458// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2459// shifting in zeros, and writes the result to the destination register. It can optionally
2460// update the condition flags based on the result.
2461bool
2462EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2463{
2464#if 0
2465 // ARM pseudo code...
2466 if ConditionPassed() then
2467 EncodingSpecificOperations();
2468 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2469 if d == 15 then // Can only occur for ARM encoding
2470 ALUWritePC(result); // setflags is always FALSE here
2471 else
2472 R[d] = result;
2473 if setflags then
2474 APSR.N = result<31>;
2475 APSR.Z = IsZeroBit(result);
2476 APSR.C = carry;
2477 // APSR.V unchanged
2478#endif
2479
2480 return EmulateShiftImm(encoding, SRType_LSL);
2481}
2482
2483// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2484// shifting in zeros, and writes the result to the destination register. The variable number
2485// of bits is read from the bottom byte of a register. It can optionally update the condition
2486// flags based on the result.
2487bool
2488EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2489{
2490#if 0
2491 // ARM pseudo code...
2492 if ConditionPassed() then
2493 EncodingSpecificOperations();
2494 shift_n = UInt(R[m]<7:0>);
2495 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2496 R[d] = result;
2497 if setflags then
2498 APSR.N = result<31>;
2499 APSR.Z = IsZeroBit(result);
2500 APSR.C = carry;
2501 // APSR.V unchanged
2502#endif
2503
2504 return EmulateShiftReg(encoding, SRType_LSL);
2505}
2506
2507// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2508// shifting in zeros, and writes the result to the destination register. It can optionally
2509// update the condition flags based on the result.
2510bool
2511EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2512{
2513#if 0
2514 // ARM pseudo code...
2515 if ConditionPassed() then
2516 EncodingSpecificOperations();
2517 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2518 if d == 15 then // Can only occur for ARM encoding
2519 ALUWritePC(result); // setflags is always FALSE here
2520 else
2521 R[d] = result;
2522 if setflags then
2523 APSR.N = result<31>;
2524 APSR.Z = IsZeroBit(result);
2525 APSR.C = carry;
2526 // APSR.V unchanged
2527#endif
2528
2529 return EmulateShiftImm(encoding, SRType_LSR);
2530}
2531
2532// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2533// shifting in zeros, and writes the result to the destination register. The variable number
2534// of bits is read from the bottom byte of a register. It can optionally update the condition
2535// flags based on the result.
2536bool
2537EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2538{
2539#if 0
2540 // ARM pseudo code...
2541 if ConditionPassed() then
2542 EncodingSpecificOperations();
2543 shift_n = UInt(R[m]<7:0>);
2544 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2545 R[d] = result;
2546 if setflags then
2547 APSR.N = result<31>;
2548 APSR.Z = IsZeroBit(result);
2549 APSR.C = carry;
2550 // APSR.V unchanged
2551#endif
2552
2553 return EmulateShiftReg(encoding, SRType_LSR);
2554}
2555
Johnny Cheneeab4852011-02-16 22:14:44 +00002556// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2557// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2558// It can optionally update the condition flags based on the result.
2559bool
2560EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2561{
2562#if 0
2563 // ARM pseudo code...
2564 if ConditionPassed() then
2565 EncodingSpecificOperations();
2566 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2567 if d == 15 then // Can only occur for ARM encoding
2568 ALUWritePC(result); // setflags is always FALSE here
2569 else
2570 R[d] = result;
2571 if setflags then
2572 APSR.N = result<31>;
2573 APSR.Z = IsZeroBit(result);
2574 APSR.C = carry;
2575 // APSR.V unchanged
2576#endif
2577
2578 return EmulateShiftImm(encoding, SRType_ROR);
2579}
2580
2581// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2582// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2583// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2584// flags based on the result.
2585bool
2586EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2587{
2588#if 0
2589 // ARM pseudo code...
2590 if ConditionPassed() then
2591 EncodingSpecificOperations();
2592 shift_n = UInt(R[m]<7:0>);
2593 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2594 R[d] = result;
2595 if setflags then
2596 APSR.N = result<31>;
2597 APSR.Z = IsZeroBit(result);
2598 APSR.C = carry;
2599 // APSR.V unchanged
2600#endif
2601
2602 return EmulateShiftReg(encoding, SRType_ROR);
2603}
2604
2605// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2606// with the carry flag shifted into bit [31].
2607//
2608// RRX can optionally update the condition flags based on the result.
2609// In that case, bit [0] is shifted into the carry flag.
2610bool
2611EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2612{
2613#if 0
2614 // ARM pseudo code...
2615 if ConditionPassed() then
2616 EncodingSpecificOperations();
2617 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2618 if d == 15 then // Can only occur for ARM encoding
2619 ALUWritePC(result); // setflags is always FALSE here
2620 else
2621 R[d] = result;
2622 if setflags then
2623 APSR.N = result<31>;
2624 APSR.Z = IsZeroBit(result);
2625 APSR.C = carry;
2626 // APSR.V unchanged
2627#endif
2628
2629 return EmulateShiftImm(encoding, SRType_RRX);
2630}
2631
Johnny Chen41a0a152011-02-16 01:27:54 +00002632bool
2633EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2634{
2635 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2636
Johnny Chen82f16aa2011-02-15 20:10:55 +00002637 bool success = false;
2638 const uint32_t opcode = OpcodeAsUnsigned (&success);
2639 if (!success)
2640 return false;
2641
2642 if (ConditionPassed())
2643 {
Johnny Chene7f89532011-02-15 23:22:46 +00002644 uint32_t Rd; // the destination register
2645 uint32_t Rm; // the first operand register
2646 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002647 uint32_t carry; // the carry bit after the shift operation
2648 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002649
2650 // Special case handling!
2651 // A8.6.139 ROR (immediate) -- Encoding T1
2652 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2653 {
2654 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2655 // have the same decoding of bit fields as the other Thumb2 shift operations.
2656 encoding = eEncodingT2;
2657 }
2658
Johnny Chen82f16aa2011-02-15 20:10:55 +00002659 switch (encoding) {
2660 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002661 // Due to the above special case handling!
2662 assert(shift_type != SRType_ROR);
2663
Johnny Chen82f16aa2011-02-15 20:10:55 +00002664 Rd = Bits32(opcode, 2, 0);
2665 Rm = Bits32(opcode, 5, 3);
2666 setflags = !InITBlock();
2667 imm5 = Bits32(opcode, 10, 6);
2668 break;
2669 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002670 // A8.6.141 RRX
2671 assert(shift_type != SRType_RRX);
2672
Johnny Chen82f16aa2011-02-15 20:10:55 +00002673 Rd = Bits32(opcode, 11, 8);
2674 Rm = Bits32(opcode, 3, 0);
2675 setflags = BitIsSet(opcode, 20);
2676 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2677 if (BadReg(Rd) || BadReg(Rm))
2678 return false;
2679 break;
2680 case eEncodingA1:
2681 Rd = Bits32(opcode, 15, 12);
2682 Rm = Bits32(opcode, 3, 0);
2683 setflags = BitIsSet(opcode, 20);
2684 imm5 = Bits32(opcode, 11, 7);
2685 break;
2686 default:
2687 return false;
2688 }
2689
Johnny Cheneeab4852011-02-16 22:14:44 +00002690 // A8.6.139 ROR (immediate)
2691 if (shift_type == SRType_ROR && imm5 == 0)
2692 shift_type = SRType_RRX;
2693
Johnny Chen82f16aa2011-02-15 20:10:55 +00002694 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002695 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002696 if (!success)
2697 return false;
2698
Johnny Cheneeab4852011-02-16 22:14:44 +00002699 // Decode the shift amount if not RRX.
2700 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002701
Johnny Chene97c0d52011-02-18 19:32:20 +00002702 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002703
2704 // The context specifies that an immediate is to be moved into Rd.
2705 EmulateInstruction::Context context;
2706 context.type = EmulateInstruction::eContextImmediate;
2707 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002708
Johnny Chen10530c22011-02-17 22:37:12 +00002709 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002710 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002711 }
2712 return true;
2713}
2714
Johnny Chene7f89532011-02-15 23:22:46 +00002715bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002716EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002717{
Johnny Chen41a0a152011-02-16 01:27:54 +00002718 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002719
2720 bool success = false;
2721 const uint32_t opcode = OpcodeAsUnsigned (&success);
2722 if (!success)
2723 return false;
2724
2725 if (ConditionPassed())
2726 {
2727 uint32_t Rd; // the destination register
2728 uint32_t Rn; // the first operand register
2729 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2730 uint32_t carry; // the carry bit after the shift operation
2731 bool setflags;
2732 switch (encoding) {
2733 case eEncodingT1:
2734 Rd = Bits32(opcode, 2, 0);
2735 Rn = Rd;
2736 Rm = Bits32(opcode, 5, 3);
2737 setflags = !InITBlock();
2738 break;
2739 case eEncodingT2:
2740 Rd = Bits32(opcode, 11, 8);
2741 Rn = Bits32(opcode, 19, 16);
2742 Rm = Bits32(opcode, 3, 0);
2743 setflags = BitIsSet(opcode, 20);
2744 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2745 return false;
2746 break;
2747 case eEncodingA1:
2748 Rd = Bits32(opcode, 15, 12);
2749 Rn = Bits32(opcode, 3, 0);
2750 Rm = Bits32(opcode, 11, 8);
2751 setflags = BitIsSet(opcode, 20);
2752 if (Rd == 15 || Rn == 15 || Rm == 15)
2753 return false;
2754 break;
2755 default:
2756 return false;
2757 }
2758
2759 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002760 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002761 if (!success)
2762 return false;
2763 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002764 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002765 if (!success)
2766 return false;
2767
2768 // Get the shift amount.
2769 uint32_t amt = Bits32(val, 7, 0);
2770
Johnny Chene97c0d52011-02-18 19:32:20 +00002771 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002772
2773 // The context specifies that an immediate is to be moved into Rd.
2774 EmulateInstruction::Context context;
2775 context.type = EmulateInstruction::eContextImmediate;
2776 context.SetNoArgs ();
2777
Johnny Chen10530c22011-02-17 22:37:12 +00002778 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002779 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002780 }
2781 return true;
2782}
2783
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002784// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002785// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002786// can be written back to the base register.
2787bool
2788EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2789{
2790#if 0
2791 // ARM pseudo code...
2792 if ConditionPassed()
2793 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2794 address = R[n];
2795
2796 for i = 0 to 14
2797 if registers<i> == '1' then
2798 R[i] = MemA[address, 4]; address = address + 4;
2799 if registers<15> == '1' then
2800 LoadWritePC (MemA[address, 4]);
2801
2802 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2803 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2804
2805#endif
2806
2807 bool success = false;
2808 const uint32_t opcode = OpcodeAsUnsigned (&success);
2809 if (!success)
2810 return false;
2811
2812 if (ConditionPassed())
2813 {
2814 uint32_t n;
2815 uint32_t registers = 0;
2816 bool wback;
2817 const uint32_t addr_byte_size = GetAddressByteSize();
2818 switch (encoding)
2819 {
2820 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002821 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002822 n = Bits32 (opcode, 10, 8);
2823 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002824 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002825 wback = BitIsClear (registers, n);
2826 // if BitCount(registers) < 1 then UNPREDICTABLE;
2827 if (BitCount(registers) < 1)
2828 return false;
2829 break;
2830 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002831 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2832 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002833 n = Bits32 (opcode, 19, 16);
2834 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002835 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002836 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002837
2838 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002839 if ((n == 15)
2840 || (BitCount (registers) < 2)
2841 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2842 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002843
2844 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002845 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002846 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002847
2848 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002849 if (wback
2850 && BitIsSet (registers, n))
2851 return false;
2852 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002853
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002854 case eEncodingA1:
2855 n = Bits32 (opcode, 19, 16);
2856 registers = Bits32 (opcode, 15, 0);
2857 wback = BitIsSet (opcode, 21);
2858 if ((n == 15)
2859 || (BitCount (registers) < 1))
2860 return false;
2861 break;
2862 default:
2863 return false;
2864 }
2865
2866 int32_t offset = 0;
2867 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2868 if (!success)
2869 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002870
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002871 EmulateInstruction::Context context;
2872 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2873 Register dwarf_reg;
2874 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2875 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002876
2877 for (int i = 0; i < 14; ++i)
2878 {
2879 if (BitIsSet (registers, i))
2880 {
Caroline Tice85aab332011-02-08 23:56:10 +00002881 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002882 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002883 if (wback && (n == 13)) // Pop Instruction
2884 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2885
2886 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002887 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002888 if (!success)
2889 return false;
2890
2891 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2892 return false;
2893
2894 offset += addr_byte_size;
2895 }
2896 }
2897
2898 if (BitIsSet (registers, 15))
2899 {
2900 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002901 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002902 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002903 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002904 if (!success)
2905 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002906 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002907 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002908 return false;
2909 }
2910
2911 if (wback && BitIsClear (registers, n))
2912 {
Caroline Ticefa172202011-02-11 22:49:54 +00002913 // R[n] = R[n] + 4 * BitCount (registers)
2914 int32_t offset = addr_byte_size * BitCount (registers);
2915 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002916 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002917
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002918 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2919 return false;
2920 }
2921 if (wback && BitIsSet (registers, n))
2922 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002923 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002924 }
2925 return true;
2926}
Caroline Tice713c2662011-02-11 17:59:55 +00002927
2928// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2929// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2930// can optionally be written back tot he base registers.
2931bool
2932EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2933{
2934#if 0
2935 // ARM pseudo code...
2936 if ConditionPassed() then
2937 EncodingSpecificOperations();
2938 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002939
Caroline Tice713c2662011-02-11 17:59:55 +00002940 for i = 0 to 14
2941 if registers<i> == ’1’ then
2942 R[i] = MemA[address,4]; address = address + 4;
2943
2944 if registers<15> == ’1’ then
2945 LoadWritePC(MemA[address,4]);
2946
2947 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2948 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2949#endif
2950
2951 bool success = false;
2952 const uint32_t opcode = OpcodeAsUnsigned (&success);
2953 if (!success)
2954 return false;
2955
2956 if (ConditionPassed())
2957 {
2958 uint32_t n;
2959 uint32_t registers = 0;
2960 bool wback;
2961 const uint32_t addr_byte_size = GetAddressByteSize();
2962
2963 // EncodingSpecificOperations();
2964 switch (encoding)
2965 {
2966 case eEncodingA1:
2967 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2968 n = Bits32 (opcode, 19, 16);
2969 registers = Bits32 (opcode, 15, 0);
2970 wback = BitIsSet (opcode, 21);
2971
2972 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2973 if ((n == 15) || (BitCount (registers) < 1))
2974 return false;
2975
2976 break;
2977
2978 default:
2979 return false;
2980 }
2981 // address = R[n] - 4*BitCount(registers) + 4;
2982
2983 int32_t offset = 0;
2984 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2985
2986 if (!success)
2987 return false;
2988
2989 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2990
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002991 EmulateInstruction::Context context;
2992 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2993 Register dwarf_reg;
2994 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2995 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002996
2997 // for i = 0 to 14
2998 for (int i = 0; i < 14; ++i)
2999 {
3000 // if registers<i> == ’1’ then
3001 if (BitIsSet (registers, i))
3002 {
3003 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003004 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003005 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003006 if (!success)
3007 return false;
3008 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3009 return false;
3010 offset += addr_byte_size;
3011 }
3012 }
3013
3014 // if registers<15> == ’1’ then
3015 // LoadWritePC(MemA[address,4]);
3016 if (BitIsSet (registers, 15))
3017 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003018 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003019 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003020 if (!success)
3021 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003022 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003023 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003024 return false;
3025 }
3026
3027 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3028 if (wback && BitIsClear (registers, n))
3029 {
Caroline Tice713c2662011-02-11 17:59:55 +00003030 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3031 if (!success)
3032 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003033
3034 offset = (addr_byte_size * BitCount (registers)) * -1;
3035 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003036 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003037 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003038 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3039 return false;
3040 }
3041
3042 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3043 if (wback && BitIsSet (registers, n))
3044 return WriteBits32Unknown (n);
3045 }
3046 return true;
3047}
3048
3049// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3050// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3051// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003052bool
3053EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3054{
3055#if 0
3056 // ARM pseudo code...
3057 if ConditionPassed() then
3058 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3059 address = R[n] - 4*BitCount(registers);
3060
3061 for i = 0 to 14
3062 if registers<i> == ’1’ then
3063 R[i] = MemA[address,4]; address = address + 4;
3064 if registers<15> == ’1’ then
3065 LoadWritePC(MemA[address,4]);
3066
3067 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3068 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3069#endif
3070
3071 bool success = false;
3072 const uint32_t opcode = OpcodeAsUnsigned (&success);
3073 if (!success)
3074 return false;
3075
3076 if (ConditionPassed())
3077 {
3078 uint32_t n;
3079 uint32_t registers = 0;
3080 bool wback;
3081 const uint32_t addr_byte_size = GetAddressByteSize();
3082 switch (encoding)
3083 {
3084 case eEncodingT1:
3085 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3086 n = Bits32 (opcode, 19, 16);
3087 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003088 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003089 wback = BitIsSet (opcode, 21);
3090
3091 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3092 if ((n == 15)
3093 || (BitCount (registers) < 2)
3094 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3095 return false;
3096
3097 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003098 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003099 return false;
3100
3101 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3102 if (wback && BitIsSet (registers, n))
3103 return false;
3104
3105 break;
3106
3107 case eEncodingA1:
3108 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3109 n = Bits32 (opcode, 19, 16);
3110 registers = Bits32 (opcode, 15, 0);
3111 wback = BitIsSet (opcode, 21);
3112
3113 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3114 if ((n == 15) || (BitCount (registers) < 1))
3115 return false;
3116
3117 break;
3118
3119 default:
3120 return false;
3121 }
3122
Caroline Tice713c2662011-02-11 17:59:55 +00003123 // address = R[n] - 4*BitCount(registers);
3124
Caroline Tice0b29e242011-02-08 23:16:02 +00003125 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003126 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3127
3128 if (!success)
3129 return false;
3130
3131 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003132 EmulateInstruction::Context context;
3133 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3134 Register dwarf_reg;
3135 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3136 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003137
3138 for (int i = 0; i < 14; ++i)
3139 {
3140 if (BitIsSet (registers, i))
3141 {
3142 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003143 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003144 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003145 if (!success)
3146 return false;
3147
3148 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3149 return false;
3150
3151 offset += addr_byte_size;
3152 }
3153 }
3154
3155 // if registers<15> == ’1’ then
3156 // LoadWritePC(MemA[address,4]);
3157 if (BitIsSet (registers, 15))
3158 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003159 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003160 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003161 if (!success)
3162 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003163 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003164 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003165 return false;
3166 }
3167
3168 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3169 if (wback && BitIsClear (registers, n))
3170 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003171 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3172 if (!success)
3173 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003174
3175 offset = (addr_byte_size * BitCount (registers)) * -1;
3176 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003177 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003178 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3180 return false;
3181 }
3182
3183 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3184 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003185 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003186 }
3187 return true;
3188}
Caroline Tice85aab332011-02-08 23:56:10 +00003189
Caroline Tice713c2662011-02-11 17:59:55 +00003190// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3191// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3192// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003193bool
3194EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3195{
3196#if 0
3197 if ConditionPassed() then
3198 EncodingSpecificOperations();
3199 address = R[n] + 4;
3200
3201 for i = 0 to 14
3202 if registers<i> == ’1’ then
3203 R[i] = MemA[address,4]; address = address + 4;
3204 if registers<15> == ’1’ then
3205 LoadWritePC(MemA[address,4]);
3206
3207 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3208 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3209#endif
3210
3211 bool success = false;
3212 const uint32_t opcode = OpcodeAsUnsigned (&success);
3213 if (!success)
3214 return false;
3215
3216 if (ConditionPassed())
3217 {
3218 uint32_t n;
3219 uint32_t registers = 0;
3220 bool wback;
3221 const uint32_t addr_byte_size = GetAddressByteSize();
3222 switch (encoding)
3223 {
3224 case eEncodingA1:
3225 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3226 n = Bits32 (opcode, 19, 16);
3227 registers = Bits32 (opcode, 15, 0);
3228 wback = BitIsSet (opcode, 21);
3229
3230 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3231 if ((n == 15) || (BitCount (registers) < 1))
3232 return false;
3233
3234 break;
3235 default:
3236 return false;
3237 }
3238 // address = R[n] + 4;
3239
3240 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003241 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3242
3243 if (!success)
3244 return false;
3245
3246 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003247
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003248 EmulateInstruction::Context context;
3249 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3250 Register dwarf_reg;
3251 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3252 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003253
3254 for (int i = 0; i < 14; ++i)
3255 {
3256 if (BitIsSet (registers, i))
3257 {
3258 // R[i] = MemA[address,4]; address = address + 4;
3259
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003260 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003261 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003262 if (!success)
3263 return false;
3264
3265 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3266 return false;
3267
3268 offset += addr_byte_size;
3269 }
3270 }
3271
3272 // if registers<15> == ’1’ then
3273 // LoadWritePC(MemA[address,4]);
3274 if (BitIsSet (registers, 15))
3275 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003276 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003277 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003278 if (!success)
3279 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003280 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003281 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003282 return false;
3283 }
3284
3285 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3286 if (wback && BitIsClear (registers, n))
3287 {
Caroline Tice85aab332011-02-08 23:56:10 +00003288 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3289 if (!success)
3290 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003291
3292 offset = addr_byte_size * BitCount (registers);
3293 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003294 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003295 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003296 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3297 return false;
3298 }
3299
3300 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3301 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003302 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003303 }
3304 return true;
3305}
Caroline Tice0b29e242011-02-08 23:16:02 +00003306
Johnny Chenef21b592011-02-10 01:52:38 +00003307// Load Register (immediate) calculates an address from a base register value and
3308// an immediate offset, loads a word from memory, and writes to a register.
3309// LDR (immediate, Thumb)
3310bool
3311EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3312{
3313#if 0
3314 // ARM pseudo code...
3315 if (ConditionPassed())
3316 {
3317 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3318 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3319 address = if index then offset_addr else R[n];
3320 data = MemU[address,4];
3321 if wback then R[n] = offset_addr;
3322 if t == 15 then
3323 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3324 elsif UnalignedSupport() || address<1:0> = '00' then
3325 R[t] = data;
3326 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3327 }
3328#endif
3329
3330 bool success = false;
3331 const uint32_t opcode = OpcodeAsUnsigned (&success);
3332 if (!success)
3333 return false;
3334
3335 if (ConditionPassed())
3336 {
3337 uint32_t Rt; // the destination register
3338 uint32_t Rn; // the base register
3339 uint32_t imm32; // the immediate offset used to form the address
3340 addr_t offset_addr; // the offset address
3341 addr_t address; // the calculated address
3342 uint32_t data; // the literal data value from memory load
3343 bool add, index, wback;
3344 switch (encoding) {
3345 case eEncodingT1:
3346 Rt = Bits32(opcode, 5, 3);
3347 Rn = Bits32(opcode, 2, 0);
3348 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3349 // index = TRUE; add = TRUE; wback = FALSE
3350 add = true;
3351 index = true;
3352 wback = false;
3353 break;
3354 default:
3355 return false;
3356 }
3357 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3358 if (!success)
3359 return false;
3360 if (add)
3361 offset_addr = base + imm32;
3362 else
3363 offset_addr = base - imm32;
3364
3365 address = (index ? offset_addr : base);
3366
3367 if (wback)
3368 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003369 EmulateInstruction::Context ctx;
3370 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3371 Register dwarf_reg;
3372 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3373 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3374
Johnny Chenef21b592011-02-10 01:52:38 +00003375 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3376 return false;
3377 }
3378
3379 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003380 EmulateInstruction::Context context;
3381 context.type = EmulateInstruction::eContextImmediate;
3382 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003383
3384 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003385 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003386 if (!success)
3387 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003388
3389 if (Rt == 15)
3390 {
3391 if (Bits32(address, 1, 0) == 0)
3392 {
Johnny Chen668b4512011-02-15 21:08:58 +00003393 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003394 return false;
3395 }
3396 else
3397 return false;
3398 }
3399 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3400 {
3401 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3402 return false;
3403 }
3404 else
3405 return false;
3406 }
3407 return true;
3408}
3409
Caroline Ticeaf556562011-02-15 18:42:15 +00003410// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3411// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3412// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003413bool
3414EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3415{
3416#if 0
3417 if ConditionPassed() then
3418 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3419 address = R[n];
3420
3421 for i = 0 to 14
3422 if registers<i> == ’1’ then
3423 if i == n && wback && i != LowestSetBit(registers) then
3424 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3425 else
3426 MemA[address,4] = R[i];
3427 address = address + 4;
3428
3429 if registers<15> == ’1’ then // Only possible for encoding A1
3430 MemA[address,4] = PCStoreValue();
3431 if wback then R[n] = R[n] + 4*BitCount(registers);
3432#endif
3433
3434 bool success = false;
3435 const uint32_t opcode = OpcodeAsUnsigned (&success);
3436 if (!success)
3437 return false;
3438
3439 if (ConditionPassed ())
3440 {
3441 uint32_t n;
3442 uint32_t registers = 0;
3443 bool wback;
3444 const uint32_t addr_byte_size = GetAddressByteSize();
3445
3446 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3447 switch (encoding)
3448 {
3449 case eEncodingT1:
3450 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3451 n = Bits32 (opcode, 10, 8);
3452 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003453 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003454 wback = true;
3455
3456 // if BitCount(registers) < 1 then UNPREDICTABLE;
3457 if (BitCount (registers) < 1)
3458 return false;
3459
3460 break;
3461
3462 case eEncodingT2:
3463 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3464 n = Bits32 (opcode, 19, 16);
3465 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003466 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003467 wback = BitIsSet (opcode, 21);
3468
3469 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3470 if ((n == 15) || (BitCount (registers) < 2))
3471 return false;
3472
3473 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3474 if (wback && BitIsSet (registers, n))
3475 return false;
3476
3477 break;
3478
3479 case eEncodingA1:
3480 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3481 n = Bits32 (opcode, 19, 16);
3482 registers = Bits32 (opcode, 15, 0);
3483 wback = BitIsSet (opcode, 21);
3484
3485 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3486 if ((n == 15) || (BitCount (registers) < 1))
3487 return false;
3488
3489 break;
3490
3491 default:
3492 return false;
3493 }
3494
3495 // address = R[n];
3496 int32_t offset = 0;
3497 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3498 if (!success)
3499 return false;
3500
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003501 EmulateInstruction::Context context;
3502 context.type = EmulateInstruction::eContextRegisterStore;
3503 Register base_reg;
3504 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003505
3506 // for i = 0 to 14
3507 for (int i = 0; i < 14; ++i)
3508 {
3509 int lowest_set_bit = 14;
3510 // if registers<i> == ’1’ then
3511 if (BitIsSet (registers, i))
3512 {
3513 if (i < lowest_set_bit)
3514 lowest_set_bit = i;
3515 // if i == n && wback && i != LowestSetBit(registers) then
3516 if ((i == n) && wback && (i != lowest_set_bit))
3517 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3518 WriteBits32UnknownToMemory (address + offset);
3519 else
3520 {
3521 // MemA[address,4] = R[i];
3522 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3523 if (!success)
3524 return false;
3525
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003526 Register data_reg;
3527 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3528 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003529 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003530 return false;
3531 }
3532
3533 // address = address + 4;
3534 offset += addr_byte_size;
3535 }
3536 }
3537
3538 // if registers<15> == ’1’ then // Only possible for encoding A1
3539 // MemA[address,4] = PCStoreValue();
3540 if (BitIsSet (registers, 15))
3541 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003542 Register pc_reg;
3543 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3544 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003545 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3546 if (!success)
3547 return false;
3548
Caroline Ticecc96eb52011-02-17 19:20:40 +00003549 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003550 return false;
3551 }
3552
3553 // if wback then R[n] = R[n] + 4*BitCount(registers);
3554 if (wback)
3555 {
3556 offset = addr_byte_size * BitCount (registers);
3557 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003558 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003559 addr_t data = address + offset;
3560 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3561 return false;
3562 }
3563 }
3564 return true;
3565}
3566
Caroline Ticeaf556562011-02-15 18:42:15 +00003567// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3568// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3569// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003570bool
3571EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3572{
3573#if 0
3574 if ConditionPassed() then
3575 EncodingSpecificOperations();
3576 address = R[n] - 4*BitCount(registers) + 4;
3577
3578 for i = 0 to 14
3579 if registers<i> == ’1’ then
3580 if i == n && wback && i != LowestSetBit(registers) then
3581 MemA[address,4] = bits(32) UNKNOWN;
3582 else
3583 MemA[address,4] = R[i];
3584 address = address + 4;
3585
3586 if registers<15> == ’1’ then
3587 MemA[address,4] = PCStoreValue();
3588
3589 if wback then R[n] = R[n] - 4*BitCount(registers);
3590#endif
3591
3592 bool success = false;
3593 const uint32_t opcode = OpcodeAsUnsigned (&success);
3594 if (!success)
3595 return false;
3596
3597 if (ConditionPassed ())
3598 {
3599 uint32_t n;
3600 uint32_t registers = 0;
3601 bool wback;
3602 const uint32_t addr_byte_size = GetAddressByteSize();
3603
3604 // EncodingSpecificOperations();
3605 switch (encoding)
3606 {
3607 case eEncodingA1:
3608 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3609 n = Bits32 (opcode, 19, 16);
3610 registers = Bits32 (opcode, 15, 0);
3611 wback = BitIsSet (opcode, 21);
3612
3613 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3614 if ((n == 15) || (BitCount (registers) < 1))
3615 return false;
3616 break;
3617 default:
3618 return false;
3619 }
3620
3621 // address = R[n] - 4*BitCount(registers) + 4;
3622 int32_t offset = 0;
3623 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3624 if (!success)
3625 return false;
3626
3627 address = address - (addr_byte_size * BitCount (registers)) + 4;
3628
3629 EmulateInstruction::Context context;
3630 context.type = EmulateInstruction::eContextRegisterStore;
3631 Register base_reg;
3632 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3633
3634 // for i = 0 to 14
3635 for (int i = 0; i < 14; ++i)
3636 {
3637 int lowest_bit_set = 14;
3638 // if registers<i> == ’1’ then
3639 if (BitIsSet (registers, i))
3640 {
3641 if (i < lowest_bit_set)
3642 lowest_bit_set = i;
3643 //if i == n && wback && i != LowestSetBit(registers) then
3644 if ((i == n) && wback && (i != lowest_bit_set))
3645 // MemA[address,4] = bits(32) UNKNOWN;
3646 WriteBits32UnknownToMemory (address + offset);
3647 else
3648 {
3649 // MemA[address,4] = R[i];
3650 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3651 if (!success)
3652 return false;
3653
3654 Register data_reg;
3655 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3656 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003657 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003658 return false;
3659 }
3660
3661 // address = address + 4;
3662 offset += addr_byte_size;
3663 }
3664 }
3665
3666 // if registers<15> == ’1’ then
3667 // MemA[address,4] = PCStoreValue();
3668 if (BitIsSet (registers, 15))
3669 {
3670 Register pc_reg;
3671 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3672 context.SetRegisterPlusOffset (pc_reg, 8);
3673 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3674 if (!success)
3675 return false;
3676
Caroline Ticecc96eb52011-02-17 19:20:40 +00003677 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003678 return false;
3679 }
3680
3681 // if wback then R[n] = R[n] - 4*BitCount(registers);
3682 if (wback)
3683 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003684 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003685 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3686 context.SetImmediateSigned (offset);
3687 addr_t data = address + offset;
3688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3689 return false;
3690 }
3691 }
3692 return true;
3693}
3694
Caroline Ticeaf556562011-02-15 18:42:15 +00003695// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3696// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3697// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003698bool
3699EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3700{
3701#if 0
3702 if ConditionPassed() then
3703 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3704 address = R[n] - 4*BitCount(registers);
3705
3706 for i = 0 to 14
3707 if registers<i> == ’1’ then
3708 if i == n && wback && i != LowestSetBit(registers) then
3709 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3710 else
3711 MemA[address,4] = R[i];
3712 address = address + 4;
3713
3714 if registers<15> == ’1’ then // Only possible for encoding A1
3715 MemA[address,4] = PCStoreValue();
3716
3717 if wback then R[n] = R[n] - 4*BitCount(registers);
3718#endif
3719
3720
3721 bool success = false;
3722 const uint32_t opcode = OpcodeAsUnsigned (&success);
3723 if (!success)
3724 return false;
3725
3726 if (ConditionPassed ())
3727 {
3728 uint32_t n;
3729 uint32_t registers = 0;
3730 bool wback;
3731 const uint32_t addr_byte_size = GetAddressByteSize();
3732
3733 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3734 switch (encoding)
3735 {
3736 case eEncodingT1:
3737 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3738 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3739 {
3740 // See PUSH
3741 }
3742 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3743 n = Bits32 (opcode, 19, 16);
3744 registers = Bits32 (opcode, 15, 0);
3745 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3746 wback = BitIsSet (opcode, 21);
3747 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3748 if ((n == 15) || BitCount (registers) < 2)
3749 return false;
3750 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3751 if (wback && BitIsSet (registers, n))
3752 return false;
3753 break;
3754
3755 case eEncodingA1:
3756 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3757 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3758 {
3759 // See Push
3760 }
3761 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3762 n = Bits32 (opcode, 19, 16);
3763 registers = Bits32 (opcode, 15, 0);
3764 wback = BitIsSet (opcode, 21);
3765 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3766 if ((n == 15) || BitCount (registers) < 1)
3767 return false;
3768 break;
3769
3770 default:
3771 return false;
3772 }
3773
3774 // address = R[n] - 4*BitCount(registers);
3775
3776 int32_t offset = 0;
3777 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3778 if (!success)
3779 return false;
3780
3781 address = address - (addr_byte_size * BitCount (registers));
3782
3783 EmulateInstruction::Context context;
3784 context.type = EmulateInstruction::eContextRegisterStore;
3785 Register base_reg;
3786 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3787
3788 // for i = 0 to 14
3789 for (int i = 0; i < 14; ++i)
3790 {
3791 uint32_t lowest_set_bit = 14;
3792 // if registers<i> == ’1’ then
3793 if (BitIsSet (registers, i))
3794 {
3795 if (i < lowest_set_bit)
3796 lowest_set_bit = i;
3797 // if i == n && wback && i != LowestSetBit(registers) then
3798 if ((i == n) && wback && (i != lowest_set_bit))
3799 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3800 WriteBits32UnknownToMemory (address + offset);
3801 else
3802 {
3803 // MemA[address,4] = R[i];
3804 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3805 if (!success)
3806 return false;
3807
3808 Register data_reg;
3809 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3810 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003811 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003812 return false;
3813 }
3814
3815 // address = address + 4;
3816 offset += addr_byte_size;
3817 }
3818 }
3819
3820 // if registers<15> == ’1’ then // Only possible for encoding A1
3821 // MemA[address,4] = PCStoreValue();
3822 if (BitIsSet (registers, 15))
3823 {
3824 Register pc_reg;
3825 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3826 context.SetRegisterPlusOffset (pc_reg, 8);
3827 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3828 if (!success)
3829 return false;
3830
Caroline Ticecc96eb52011-02-17 19:20:40 +00003831 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003832 return false;
3833 }
3834
3835 // if wback then R[n] = R[n] - 4*BitCount(registers);
3836 if (wback)
3837 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003838 offset = (addr_byte_size * BitCount (registers)) * -1;
3839 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3840 context.SetImmediateSigned (offset);
3841 addr_t data = address + offset;
3842 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3843 return false;
3844 }
3845 }
3846 return true;
3847}
3848
3849// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3850// from a base register. The consecutive memory locations start just above this address, and the address of the last
3851// of those locations can optionally be written back to the base register.
3852bool
3853EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3854{
3855#if 0
3856 if ConditionPassed() then
3857 EncodingSpecificOperations();
3858 address = R[n] + 4;
3859
3860 for i = 0 to 14
3861 if registers<i> == ’1’ then
3862 if i == n && wback && i != LowestSetBit(registers) then
3863 MemA[address,4] = bits(32) UNKNOWN;
3864 else
3865 MemA[address,4] = R[i];
3866 address = address + 4;
3867
3868 if registers<15> == ’1’ then
3869 MemA[address,4] = PCStoreValue();
3870
3871 if wback then R[n] = R[n] + 4*BitCount(registers);
3872#endif
3873
3874 bool success = false;
3875 const uint32_t opcode = OpcodeAsUnsigned (&success);
3876 if (!success)
3877 return false;
3878
3879 if (ConditionPassed())
3880 {
3881 uint32_t n;
3882 uint32_t registers = 0;
3883 bool wback;
3884 const uint32_t addr_byte_size = GetAddressByteSize();
3885
3886 // EncodingSpecificOperations();
3887 switch (encoding)
3888 {
3889 case eEncodingA1:
3890 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3891 n = Bits32 (opcode, 19, 16);
3892 registers = Bits32 (opcode, 15, 0);
3893 wback = BitIsSet (opcode, 21);
3894
3895 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3896 if ((n == 15) && (BitCount (registers) < 1))
3897 return false;
3898 break;
3899 default:
3900 return false;
3901 }
3902 // address = R[n] + 4;
3903
3904 int32_t offset = 0;
3905 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3906 if (!success)
3907 return false;
3908
3909 address = address + addr_byte_size;
3910
3911 EmulateInstruction::Context context;
3912 context.type = EmulateInstruction::eContextRegisterStore;
3913 Register base_reg;
3914 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3915
3916 uint32_t lowest_set_bit = 14;
3917 // for i = 0 to 14
3918 for (int i = 0; i < 14; ++i)
3919 {
3920 // if registers<i> == ’1’ then
3921 if (BitIsSet (registers, i))
3922 {
3923 if (i < lowest_set_bit)
3924 lowest_set_bit = i;
3925 // if i == n && wback && i != LowestSetBit(registers) then
3926 if ((i == n) && wback && (i != lowest_set_bit))
3927 // MemA[address,4] = bits(32) UNKNOWN;
3928 WriteBits32UnknownToMemory (address + offset);
3929 // else
3930 else
3931 {
3932 // MemA[address,4] = R[i];
3933 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3934 if (!success)
3935 return false;
3936
3937 Register data_reg;
3938 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3939 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003940 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003941 return false;
3942 }
3943
3944 // address = address + 4;
3945 offset += addr_byte_size;
3946 }
3947 }
3948
3949 // if registers<15> == ’1’ then
3950 // MemA[address,4] = PCStoreValue();
3951 if (BitIsSet (registers, 15))
3952 {
3953 Register pc_reg;
3954 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3955 context.SetRegisterPlusOffset (pc_reg, 8);
3956 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3957 if (!success)
3958 return false;
3959
Caroline Ticecc96eb52011-02-17 19:20:40 +00003960 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003961 return false;
3962 }
3963
3964 // if wback then R[n] = R[n] + 4*BitCount(registers);
3965 if (wback)
3966 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003967 offset = addr_byte_size * BitCount (registers);
3968 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3969 context.SetImmediateSigned (offset);
3970 addr_t data = address + offset;
3971 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3972 return false;
3973 }
3974 }
3975 return true;
3976}
Caroline Tice7fac8572011-02-15 22:53:54 +00003977
3978// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3979// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3980bool
3981EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3982{
3983#if 0
3984 if ConditionPassed() then
3985 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3986 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3987 address = if index then offset_addr else R[n];
3988 if UnalignedSupport() || address<1:0> == ’00’ then
3989 MemU[address,4] = R[t];
3990 else // Can only occur before ARMv7
3991 MemU[address,4] = bits(32) UNKNOWN;
3992 if wback then R[n] = offset_addr;
3993#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003994
Caroline Tice7fac8572011-02-15 22:53:54 +00003995 bool success = false;
3996 const uint32_t opcode = OpcodeAsUnsigned (&success);
3997 if (!success)
3998 return false;
3999
4000 if (ConditionPassed())
4001 {
4002 const uint32_t addr_byte_size = GetAddressByteSize();
4003
4004 uint32_t t;
4005 uint32_t n;
4006 uint32_t imm32;
4007 bool index;
4008 bool add;
4009 bool wback;
4010 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4011 switch (encoding)
4012 {
4013 case eEncodingT1:
4014 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4015 t = Bits32 (opcode, 2, 0);
4016 n = Bits32 (opcode, 5, 3);
4017 imm32 = Bits32 (opcode, 10, 6) << 2;
4018
4019 // index = TRUE; add = TRUE; wback = FALSE;
4020 index = true;
4021 add = false;
4022 wback = false;
4023 break;
4024
4025 case eEncodingT2:
4026 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4027 t = Bits32 (opcode, 10, 8);
4028 n = 13;
4029 imm32 = Bits32 (opcode, 7, 0) << 2;
4030
4031 // index = TRUE; add = TRUE; wback = FALSE;
4032 index = true;
4033 add = true;
4034 wback = false;
4035 break;
4036
4037 case eEncodingT3:
4038 // if Rn == ’1111’ then UNDEFINED;
4039 if (Bits32 (opcode, 19, 16) == 15)
4040 return false;
4041
4042 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4043 t = Bits32 (opcode, 15, 12);
4044 n = Bits32 (opcode, 19, 16);
4045 imm32 = Bits32 (opcode, 11, 0);
4046
4047 // index = TRUE; add = TRUE; wback = FALSE;
4048 index = true;
4049 add = true;
4050 wback = false;
4051
4052 // if t == 15 then UNPREDICTABLE;
4053 if (t == 15)
4054 return false;
4055 break;
4056
4057 case eEncodingT4:
4058 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4059 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4060 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4061 if ((Bits32 (opcode, 19, 16) == 15)
4062 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4063 return false;
4064
4065 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4066 t = Bits32 (opcode, 15, 12);
4067 n = Bits32 (opcode, 19, 16);
4068 imm32 = Bits32 (opcode, 7, 0);
4069
4070 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4071 index = BitIsSet (opcode, 10);
4072 add = BitIsSet (opcode, 9);
4073 wback = BitIsSet (opcode, 8);
4074
4075 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4076 if ((t == 15) || (wback && (n == t)))
4077 return false;
4078 break;
4079
4080 default:
4081 return false;
4082 }
4083
4084 addr_t offset_addr;
4085 addr_t address;
4086
4087 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4088 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4089 if (!success)
4090 return false;
4091
4092 if (add)
4093 offset_addr = base_address + imm32;
4094 else
4095 offset_addr = base_address - imm32;
4096
4097 // address = if index then offset_addr else R[n];
4098 if (index)
4099 address = offset_addr;
4100 else
4101 address = base_address;
4102
4103 EmulateInstruction::Context context;
4104 context.type = eContextRegisterStore;
4105 Register base_reg;
4106 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4107
4108 // if UnalignedSupport() || address<1:0> == ’00’ then
4109 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4110 {
4111 // MemU[address,4] = R[t];
4112 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4113 if (!success)
4114 return false;
4115
4116 Register data_reg;
4117 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4118 int32_t offset = address - base_address;
4119 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004120 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004121 return false;
4122 }
4123 else
4124 {
4125 // MemU[address,4] = bits(32) UNKNOWN;
4126 WriteBits32UnknownToMemory (address);
4127 }
4128
4129 // if wback then R[n] = offset_addr;
4130 if (wback)
4131 {
4132 context.type = eContextRegisterLoad;
4133 context.SetAddress (offset_addr);
4134 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4135 return false;
4136 }
4137 }
4138 return true;
4139}
Caroline Ticeaf556562011-02-15 18:42:15 +00004140
Caroline Tice3fd63e92011-02-16 00:33:43 +00004141// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4142// word from a register to memory. The offset register value can optionally be shifted.
4143bool
4144EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4145{
4146#if 0
4147 if ConditionPassed() then
4148 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4149 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4150 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4151 address = if index then offset_addr else R[n];
4152 if t == 15 then // Only possible for encoding A1
4153 data = PCStoreValue();
4154 else
4155 data = R[t];
4156 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4157 MemU[address,4] = data;
4158 else // Can only occur before ARMv7
4159 MemU[address,4] = bits(32) UNKNOWN;
4160 if wback then R[n] = offset_addr;
4161#endif
4162
4163 bool success = false;
4164 const uint32_t opcode = OpcodeAsUnsigned (&success);
4165 if (!success)
4166 return false;
4167
4168 if (ConditionPassed())
4169 {
4170 const uint32_t addr_byte_size = GetAddressByteSize();
4171
4172 uint32_t t;
4173 uint32_t n;
4174 uint32_t m;
4175 ARM_ShifterType shift_t;
4176 uint32_t shift_n;
4177 bool index;
4178 bool add;
4179 bool wback;
4180
4181 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4182 switch (encoding)
4183 {
4184 case eEncodingT1:
4185 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4186 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4187 t = Bits32 (opcode, 2, 0);
4188 n = Bits32 (opcode, 5, 3);
4189 m = Bits32 (opcode, 8, 6);
4190
4191 // index = TRUE; add = TRUE; wback = FALSE;
4192 index = true;
4193 add = true;
4194 wback = false;
4195
4196 // (shift_t, shift_n) = (SRType_LSL, 0);
4197 shift_t = SRType_LSL;
4198 shift_n = 0;
4199 break;
4200
4201 case eEncodingT2:
4202 // if Rn == ’1111’ then UNDEFINED;
4203 if (Bits32 (opcode, 19, 16) == 15)
4204 return false;
4205
4206 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4207 t = Bits32 (opcode, 15, 12);
4208 n = Bits32 (opcode, 19, 16);
4209 m = Bits32 (opcode, 3, 0);
4210
4211 // index = TRUE; add = TRUE; wback = FALSE;
4212 index = true;
4213 add = true;
4214 wback = false;
4215
4216 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4217 shift_t = SRType_LSL;
4218 shift_n = Bits32 (opcode, 5, 4);
4219
4220 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4221 if ((t == 15) || (BadReg (m)))
4222 return false;
4223 break;
4224
4225 case eEncodingA1:
4226 {
4227 // if P == ’0’ && W == ’1’ then SEE STRT;
4228 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4229 t = Bits32 (opcode, 15, 12);
4230 n = Bits32 (opcode, 19, 16);
4231 m = Bits32 (opcode, 3, 0);
4232
4233 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4234 index = BitIsSet (opcode, 24);
4235 add = BitIsSet (opcode, 23);
4236 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4237
4238 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4239 uint32_t typ = Bits32 (opcode, 6, 5);
4240 uint32_t imm5 = Bits32 (opcode, 11, 7);
4241 shift_n = DecodeImmShift(typ, imm5, shift_t);
4242
4243 // if m == 15 then UNPREDICTABLE;
4244 if (m == 15)
4245 return false;
4246
4247 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4248 if (wback && ((n == 15) || (n == t)))
4249 return false;
4250
4251 break;
4252 }
4253 default:
4254 return false;
4255 }
4256
4257 addr_t offset_addr;
4258 addr_t address;
4259 int32_t offset = 0;
4260
4261 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4262 if (!success)
4263 return false;
4264
4265 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4266 if (!success)
4267 return false;
4268
4269 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004270 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004271
4272 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4273 if (add)
4274 offset_addr = base_address + offset;
4275 else
4276 offset_addr = base_address - offset;
4277
4278 // address = if index then offset_addr else R[n];
4279 if (index)
4280 address = offset_addr;
4281 else
4282 address = base_address;
4283
4284 uint32_t data;
4285 // if t == 15 then // Only possible for encoding A1
4286 if (t == 15)
4287 // data = PCStoreValue();
4288 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4289 else
4290 // data = R[t];
4291 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4292
4293 if (!success)
4294 return false;
4295
4296 EmulateInstruction::Context context;
4297 context.type = eContextRegisterStore;
4298
4299 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4300 if (UnalignedSupport ()
4301 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4302 || CurrentInstrSet() == eModeARM)
4303 {
4304 // MemU[address,4] = data;
4305
4306 Register base_reg;
4307 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4308
4309 Register data_reg;
4310 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4311
4312 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004313 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004314 return false;
4315
4316 }
4317 else
4318 // MemU[address,4] = bits(32) UNKNOWN;
4319 WriteBits32UnknownToMemory (address);
4320
4321 // if wback then R[n] = offset_addr;
4322 if (wback)
4323 {
4324 context.type = eContextRegisterLoad;
4325 context.SetAddress (offset_addr);
4326 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4327 return false;
4328 }
4329
4330 }
4331 return true;
4332}
Caroline Tice73a29de2011-02-16 20:22:22 +00004333
4334bool
4335EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4336{
4337#if 0
4338 if ConditionPassed() then
4339 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4340 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4341 address = if index then offset_addr else R[n];
4342 MemU[address,1] = R[t]<7:0>;
4343 if wback then R[n] = offset_addr;
4344#endif
4345
4346
4347 bool success = false;
4348 const uint32_t opcode = OpcodeAsUnsigned (&success);
4349 if (!success)
4350 return false;
4351
4352 if (ConditionPassed ())
4353 {
4354 uint32_t t;
4355 uint32_t n;
4356 uint32_t imm32;
4357 bool index;
4358 bool add;
4359 bool wback;
4360 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4361 switch (encoding)
4362 {
4363 case eEncodingT1:
4364 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4365 t = Bits32 (opcode, 2, 0);
4366 n = Bits32 (opcode, 5, 3);
4367 imm32 = Bits32 (opcode, 10, 6);
4368
4369 // index = TRUE; add = TRUE; wback = FALSE;
4370 index = true;
4371 add = true;
4372 wback = false;
4373 break;
4374
4375 case eEncodingT2:
4376 // if Rn == ’1111’ then UNDEFINED;
4377 if (Bits32 (opcode, 19, 16) == 15)
4378 return false;
4379
4380 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4381 t = Bits32 (opcode, 15, 12);
4382 n = Bits32 (opcode, 19, 16);
4383 imm32 = Bits32 (opcode, 11, 0);
4384
4385 // index = TRUE; add = TRUE; wback = FALSE;
4386 index = true;
4387 add = true;
4388 wback = false;
4389
4390 // if BadReg(t) then UNPREDICTABLE;
4391 if (BadReg (t))
4392 return false;
4393 break;
4394
4395 case eEncodingT3:
4396 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4397 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4398 if (Bits32 (opcode, 19, 16) == 15)
4399 return false;
4400
4401 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4402 t = Bits32 (opcode, 15, 12);
4403 n = Bits32 (opcode, 19, 16);
4404 imm32 = Bits32 (opcode, 7, 0);
4405
4406 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4407 index = BitIsSet (opcode, 10);
4408 add = BitIsSet (opcode, 9);
4409 wback = BitIsSet (opcode, 8);
4410
4411 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4412 if ((BadReg (t)) || (wback && (n == t)))
4413 return false;
4414 break;
4415
4416 default:
4417 return false;
4418 }
4419
4420 addr_t offset_addr;
4421 addr_t address;
4422 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4423 if (!success)
4424 return false;
4425
4426 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4427 if (add)
4428 offset_addr = base_address + imm32;
4429 else
4430 offset_addr = base_address - imm32;
4431
4432 // address = if index then offset_addr else R[n];
4433 if (index)
4434 address = offset_addr;
4435 else
4436 address = base_address;
4437
Caroline Ticecc96eb52011-02-17 19:20:40 +00004438 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004439 Register base_reg;
4440 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4441
4442 Register data_reg;
4443 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4444
4445 EmulateInstruction::Context context;
4446 context.type = eContextRegisterStore;
4447 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4448
4449 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4450 if (!success)
4451 return false;
4452
4453 data = Bits32 (data, 7, 0);
4454
Caroline Ticecc96eb52011-02-17 19:20:40 +00004455 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004456 return false;
4457
4458 // if wback then R[n] = offset_addr;
4459 if (wback)
4460 {
4461 context.type = eContextRegisterLoad;
4462 context.SetAddress (offset_addr);
4463 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4464 return false;
4465 }
4466
4467 }
4468
4469 return true;
4470}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004471
Johnny Chen157b9592011-02-18 21:13:05 +00004472// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4473// and writes the result to the destination register. It can optionally update the condition flags
4474// based on the result.
4475bool
4476EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4477{
4478#if 0
4479 // ARM pseudo code...
4480 if ConditionPassed() then
4481 EncodingSpecificOperations();
4482 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4483 if d == 15 then // Can only occur for ARM encoding
4484 ALUWritePC(result); // setflags is always FALSE here
4485 else
4486 R[d] = result;
4487 if setflags then
4488 APSR.N = result<31>;
4489 APSR.Z = IsZeroBit(result);
4490 APSR.C = carry;
4491 APSR.V = overflow;
4492#endif
4493
4494 bool success = false;
4495 const uint32_t opcode = OpcodeAsUnsigned (&success);
4496 if (!success)
4497 return false;
4498
4499 if (ConditionPassed())
4500 {
4501 uint32_t Rd, Rn;
4502 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4503 bool setflags;
4504 switch (encoding)
4505 {
4506 case eEncodingT1:
4507 Rd = Bits32(opcode, 11, 8);
4508 Rn = Bits32(opcode, 19, 16);
4509 setflags = BitIsSet(opcode, 20);
4510 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4511 if (BadReg(Rd) || BadReg(Rn))
4512 return false;
4513 break;
4514 case eEncodingA1:
4515 Rd = Bits32(opcode, 15, 12);
4516 Rn = Bits32(opcode, 19, 16);
4517 setflags = BitIsSet(opcode, 20);
4518 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4519 // TODO: Emulate SUBS PC, LR and related instructions.
4520 if (Rd == 15 && setflags)
4521 return false;
4522 break;
4523 default:
4524 return false;
4525 }
4526
4527 // Read the first operand.
4528 int32_t val1 = ReadCoreReg(Rn, &success);
4529 if (!success)
4530 return false;
4531
4532 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4533
4534 EmulateInstruction::Context context;
4535 context.type = EmulateInstruction::eContextImmediate;
4536 context.SetNoArgs ();
4537
4538 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4539 return false;
4540 }
4541 return true;
4542}
4543
4544// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4545// register value, and writes the result to the destination register. It can optionally update the
4546// condition flags based on the result.
4547bool
4548EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4549{
4550#if 0
4551 // ARM pseudo code...
4552 if ConditionPassed() then
4553 EncodingSpecificOperations();
4554 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4555 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4556 if d == 15 then // Can only occur for ARM encoding
4557 ALUWritePC(result); // setflags is always FALSE here
4558 else
4559 R[d] = result;
4560 if setflags then
4561 APSR.N = result<31>;
4562 APSR.Z = IsZeroBit(result);
4563 APSR.C = carry;
4564 APSR.V = overflow;
4565#endif
4566
4567 bool success = false;
4568 const uint32_t opcode = OpcodeAsUnsigned (&success);
4569 if (!success)
4570 return false;
4571
4572 if (ConditionPassed())
4573 {
4574 uint32_t Rd, Rn, Rm;
4575 ARM_ShifterType shift_t;
4576 uint32_t shift_n; // the shift applied to the value read from Rm
4577 bool setflags;
4578 switch (encoding)
4579 {
4580 case eEncodingT1:
4581 Rd = Rn = Bits32(opcode, 2, 0);
4582 Rm = Bits32(opcode, 5, 3);
4583 setflags = !InITBlock();
4584 shift_t = SRType_LSL;
4585 shift_n = 0;
4586 case eEncodingT2:
4587 Rd = Bits32(opcode, 11, 8);
4588 Rn = Bits32(opcode, 19, 16);
4589 Rm = Bits32(opcode, 3, 0);
4590 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004591 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004592 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4593 return false;
4594 break;
4595 case eEncodingA1:
4596 Rd = Bits32(opcode, 15, 12);
4597 Rn = Bits32(opcode, 19, 16);
4598 Rm = Bits32(opcode, 3, 0);
4599 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004600 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004601 // TODO: Emulate SUBS PC, LR and related instructions.
4602 if (Rd == 15 && setflags)
4603 return false;
4604 break;
4605 default:
4606 return false;
4607 }
4608
4609 // Read the first operand.
4610 int32_t val1 = ReadCoreReg(Rn, &success);
4611 if (!success)
4612 return false;
4613
4614 // Read the second operand.
4615 int32_t val2 = ReadCoreReg(Rm, &success);
4616 if (!success)
4617 return false;
4618
4619 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4620 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4621
4622 EmulateInstruction::Context context;
4623 context.type = EmulateInstruction::eContextImmediate;
4624 context.SetNoArgs ();
4625
4626 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4627 return false;
4628 }
4629 return true;
4630}
4631
Johnny Chene97c0d52011-02-18 19:32:20 +00004632// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4633// to the destination register. It can optionally update the condition flags based on the result.
4634bool
4635EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4636{
4637#if 0
4638 // ARM pseudo code...
4639 if ConditionPassed() then
4640 EncodingSpecificOperations();
4641 result = R[n] AND imm32;
4642 if d == 15 then // Can only occur for ARM encoding
4643 ALUWritePC(result); // setflags is always FALSE here
4644 else
4645 R[d] = result;
4646 if setflags then
4647 APSR.N = result<31>;
4648 APSR.Z = IsZeroBit(result);
4649 APSR.C = carry;
4650 // APSR.V unchanged
4651#endif
4652
4653 bool success = false;
4654 const uint32_t opcode = OpcodeAsUnsigned (&success);
4655 if (!success)
4656 return false;
4657
4658 if (ConditionPassed())
4659 {
4660 uint32_t Rd, Rn;
4661 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4662 bool setflags;
4663 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4664 switch (encoding)
4665 {
4666 case eEncodingT1:
4667 Rd = Bits32(opcode, 11, 8);
4668 Rn = Bits32(opcode, 19, 16);
4669 setflags = BitIsSet(opcode, 20);
4670 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004671 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004672 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004673 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004674 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4675 return false;
4676 break;
4677 case eEncodingA1:
4678 Rd = Bits32(opcode, 15, 12);
4679 Rn = Bits32(opcode, 19, 16);
4680 setflags = BitIsSet(opcode, 20);
4681 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4682 // TODO: Emulate SUBS PC, LR and related instructions.
4683 if (Rd == 15 && setflags)
4684 return false;
4685 break;
4686 default:
4687 return false;
4688 }
4689
Johnny Chene97c0d52011-02-18 19:32:20 +00004690 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004691 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004692 if (!success)
4693 return false;
4694
4695 uint32_t result = val1 & imm32;
4696
4697 EmulateInstruction::Context context;
4698 context.type = EmulateInstruction::eContextImmediate;
4699 context.SetNoArgs ();
4700
4701 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4702 return false;
4703 }
4704 return true;
4705}
4706
4707// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4708// and writes the result to the destination register. It can optionally update the condition flags
4709// based on the result.
4710bool
4711EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4712{
4713#if 0
4714 // ARM pseudo code...
4715 if ConditionPassed() then
4716 EncodingSpecificOperations();
4717 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4718 result = R[n] AND shifted;
4719 if d == 15 then // Can only occur for ARM encoding
4720 ALUWritePC(result); // setflags is always FALSE here
4721 else
4722 R[d] = result;
4723 if setflags then
4724 APSR.N = result<31>;
4725 APSR.Z = IsZeroBit(result);
4726 APSR.C = carry;
4727 // APSR.V unchanged
4728#endif
4729
4730 bool success = false;
4731 const uint32_t opcode = OpcodeAsUnsigned (&success);
4732 if (!success)
4733 return false;
4734
4735 if (ConditionPassed())
4736 {
4737 uint32_t Rd, Rn, Rm;
4738 ARM_ShifterType shift_t;
4739 uint32_t shift_n; // the shift applied to the value read from Rm
4740 bool setflags;
4741 uint32_t carry;
4742 switch (encoding)
4743 {
4744 case eEncodingT1:
4745 Rd = Rn = Bits32(opcode, 2, 0);
4746 Rm = Bits32(opcode, 5, 3);
4747 setflags = !InITBlock();
4748 shift_t = SRType_LSL;
4749 shift_n = 0;
4750 case eEncodingT2:
4751 Rd = Bits32(opcode, 11, 8);
4752 Rn = Bits32(opcode, 19, 16);
4753 Rm = Bits32(opcode, 3, 0);
4754 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004755 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004756 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004757 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004758 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004759 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4760 return false;
4761 break;
4762 case eEncodingA1:
4763 Rd = Bits32(opcode, 15, 12);
4764 Rn = Bits32(opcode, 19, 16);
4765 Rm = Bits32(opcode, 3, 0);
4766 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004767 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004768 // TODO: Emulate SUBS PC, LR and related instructions.
4769 if (Rd == 15 && setflags)
4770 return false;
4771 break;
4772 default:
4773 return false;
4774 }
4775
Johnny Chene97c0d52011-02-18 19:32:20 +00004776 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004777 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004778 if (!success)
4779 return false;
4780
4781 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004782 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004783 if (!success)
4784 return false;
4785
4786 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4787 uint32_t result = val1 & shifted;
4788
4789 EmulateInstruction::Context context;
4790 context.type = EmulateInstruction::eContextImmediate;
4791 context.SetNoArgs ();
4792
4793 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4794 return false;
4795 }
4796 return true;
4797}
4798
Caroline Tice4d729c52011-02-18 00:55:53 +00004799// 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 +00004800// 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 +00004801bool
4802EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4803{
4804#if 0
4805 if ConditionPassed() then
4806 EncodingSpecificOperations();
4807 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4808 address = if index then offset_addr else R[n];
4809 data = MemU[address,4];
4810 if wback then R[n] = offset_addr;
4811 if t == 15 then
4812 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4813 elsif UnalignedSupport() || address<1:0> = ’00’ then
4814 R[t] = data;
4815 else // Can only apply before ARMv7
4816 R[t] = ROR(data, 8*UInt(address<1:0>));
4817#endif
4818
4819 bool success = false;
4820 const uint32_t opcode = OpcodeAsUnsigned (&success);
4821 if (!success)
4822 return false;
4823
4824 if (ConditionPassed ())
4825 {
4826 const uint32_t addr_byte_size = GetAddressByteSize();
4827
4828 uint32_t t;
4829 uint32_t n;
4830 uint32_t imm32;
4831 bool index;
4832 bool add;
4833 bool wback;
4834
4835 switch (encoding)
4836 {
4837 case eEncodingA1:
4838 // if Rn == ’1111’ then SEE LDR (literal);
4839 // if P == ’0’ && W == ’1’ then SEE LDRT;
4840 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4841 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4842 t = Bits32 (opcode, 15, 12);
4843 n = Bits32 (opcode, 19, 16);
4844 imm32 = Bits32 (opcode, 11, 0);
4845
4846 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4847 index = BitIsSet (opcode, 24);
4848 add = BitIsSet (opcode, 23);
4849 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4850
4851 // if wback && n == t then UNPREDICTABLE;
4852 if (wback && (n == t))
4853 return false;
4854
4855 break;
4856
4857 default:
4858 return false;
4859 }
4860
4861 addr_t address;
4862 addr_t offset_addr;
4863 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4864 if (!success)
4865 return false;
4866
4867 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4868 if (add)
4869 offset_addr = base_address + imm32;
4870 else
4871 offset_addr = base_address - imm32;
4872
4873 // address = if index then offset_addr else R[n];
4874 if (index)
4875 address = offset_addr;
4876 else
4877 address = base_address;
4878
4879 // data = MemU[address,4];
4880
4881 Register base_reg;
4882 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4883
4884 EmulateInstruction::Context context;
4885 context.type = eContextRegisterLoad;
4886 context.SetRegisterPlusOffset (base_reg, address - base_address);
4887
4888 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4889 if (!success)
4890 return false;
4891
4892 // if wback then R[n] = offset_addr;
4893 if (wback)
4894 {
4895 context.type = eContextAdjustBaseRegister;
4896 context.SetAddress (offset_addr);
4897 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4898 return false;
4899 }
4900
4901 // if t == 15 then
4902 if (t == 15)
4903 {
4904 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4905 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4906 {
4907 // LoadWritePC (data);
4908 context.type = eContextRegisterLoad;
4909 context.SetRegisterPlusOffset (base_reg, address - base_address);
4910 LoadWritePC (context, data);
4911 }
4912 else
4913 return false;
4914 }
4915 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4916 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4917 {
4918 // R[t] = data;
4919 context.type = eContextRegisterLoad;
4920 context.SetRegisterPlusOffset (base_reg, address - base_address);
4921 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4922 return false;
4923 }
4924 // else // Can only apply before ARMv7
4925 else
4926 {
4927 // R[t] = ROR(data, 8*UInt(address<1:0>));
4928 data = ROR (data, Bits32 (address, 1, 0));
4929 context.type = eContextRegisterLoad;
4930 context.SetImmediate (data);
4931 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4932 return false;
4933 }
4934
4935 }
4936 return true;
4937}
4938
Caroline Ticefe479112011-02-18 18:52:37 +00004939// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4940// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4941bool
4942EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4943{
4944#if 0
4945 if ConditionPassed() then
4946 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4947 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4948 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4949 address = if index then offset_addr else R[n];
4950 data = MemU[address,4];
4951 if wback then R[n] = offset_addr;
4952 if t == 15 then
4953 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4954 elsif UnalignedSupport() || address<1:0> = ’00’ then
4955 R[t] = data;
4956 else // Can only apply before ARMv7
4957 if CurrentInstrSet() == InstrSet_ARM then
4958 R[t] = ROR(data, 8*UInt(address<1:0>));
4959 else
4960 R[t] = bits(32) UNKNOWN;
4961#endif
4962
4963 bool success = false;
4964 const uint32_t opcode = OpcodeAsUnsigned (&success);
4965 if (!success)
4966 return false;
4967
4968 if (ConditionPassed ())
4969 {
4970 const uint32_t addr_byte_size = GetAddressByteSize();
4971
4972 uint32_t t;
4973 uint32_t n;
4974 uint32_t m;
4975 bool index;
4976 bool add;
4977 bool wback;
4978 ARM_ShifterType shift_t;
4979 uint32_t shift_n;
4980
4981 switch (encoding)
4982 {
4983 case eEncodingT1:
4984 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4985 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4986 t = Bits32 (opcode, 2, 0);
4987 n = Bits32 (opcode, 5, 3);
4988 m = Bits32 (opcode, 8, 6);
4989
4990 // index = TRUE; add = TRUE; wback = FALSE;
4991 index = true;
4992 add = true;
4993 wback = false;
4994
4995 // (shift_t, shift_n) = (SRType_LSL, 0);
4996 shift_t = SRType_LSL;
4997 shift_n = 0;
4998
4999 break;
5000
5001 case eEncodingT2:
5002 // if Rn == ’1111’ then SEE LDR (literal);
5003 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5004 t = Bits32 (opcode, 15, 12);
5005 n = Bits32 (opcode, 19, 16);
5006 m = Bits32 (opcode, 3, 0);
5007
5008 // index = TRUE; add = TRUE; wback = FALSE;
5009 index = true;
5010 add = true;
5011 wback = false;
5012
5013 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5014 shift_t = SRType_LSL;
5015 shift_n = Bits32 (opcode, 5, 4);
5016
5017 // if BadReg(m) then UNPREDICTABLE;
5018 if (BadReg (m))
5019 return false;
5020
5021 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5022 if ((t == 15) && InITBlock() && !LastInITBlock())
5023 return false;
5024
5025 break;
5026
5027 case eEncodingA1:
5028 {
5029 // if P == ’0’ && W == ’1’ then SEE LDRT;
5030 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5031 t = Bits32 (opcode, 15, 12);
5032 n = Bits32 (opcode, 19, 16);
5033 m = Bits32 (opcode, 3, 0);
5034
5035 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5036 index = BitIsSet (opcode, 24);
5037 add = BitIsSet (opcode, 23);
5038 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5039
5040 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5041 uint32_t type = Bits32 (opcode, 6, 5);
5042 uint32_t imm5 = Bits32 (opcode, 11, 7);
5043 shift_n = DecodeImmShift (type, imm5, shift_t);
5044
5045 // if m == 15 then UNPREDICTABLE;
5046 if (m == 15)
5047 return false;
5048
5049 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5050 if (wback && ((n == 15) || (n == t)))
5051 return false;
5052 }
5053 break;
5054
5055
5056 default:
5057 return false;
5058 }
5059
5060 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5061 if (!success)
5062 return false;
5063
5064 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5065 if (!success)
5066 return false;
5067
5068 addr_t offset_addr;
5069 addr_t address;
5070
5071 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
5072 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
5073
5074 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5075 if (add)
5076 offset_addr = Rn + offset;
5077 else
5078 offset_addr = Rn - offset;
5079
5080 // address = if index then offset_addr else R[n];
5081 if (index)
5082 address = offset_addr;
5083 else
5084 address = Rn;
5085
5086 // data = MemU[address,4];
5087 Register base_reg;
5088 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5089
5090 EmulateInstruction::Context context;
5091 context.type = eContextRegisterLoad;
5092 context.SetRegisterPlusOffset (base_reg, address - Rn);
5093
5094 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5095 if (!success)
5096 return false;
5097
5098 // if wback then R[n] = offset_addr;
5099 if (wback)
5100 {
5101 context.type = eContextAdjustBaseRegister;
5102 context.SetAddress (offset_addr);
5103 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5104 return false;
5105 }
5106
5107 // if t == 15 then
5108 if (t == 15)
5109 {
5110 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5111 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5112 {
5113 context.type = eContextRegisterLoad;
5114 context.SetRegisterPlusOffset (base_reg, address - Rn);
5115 LoadWritePC (context, data);
5116 }
5117 else
5118 return false;
5119 }
5120 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5121 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5122 {
5123 // R[t] = data;
5124 context.type = eContextRegisterLoad;
5125 context.SetRegisterPlusOffset (base_reg, address - Rn);
5126 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5127 return false;
5128 }
5129 else // Can only apply before ARMv7
5130 {
5131 // if CurrentInstrSet() == InstrSet_ARM then
5132 if (CurrentInstrSet () == eModeARM)
5133 {
5134 // R[t] = ROR(data, 8*UInt(address<1:0>));
5135 data = ROR (data, Bits32 (address, 1, 0));
5136 context.type = eContextRegisterLoad;
5137 context.SetImmediate (data);
5138 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5139 return false;
5140 }
5141 else
5142 {
5143 // R[t] = bits(32) UNKNOWN;
5144 WriteBits32Unknown (t);
5145 }
5146 }
5147 }
5148 return true;
5149}
Caroline Tice21b604b2011-02-18 21:06:04 +00005150
5151// LDRB (immediate, Thumb)
5152bool
5153EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5154{
5155#if 0
5156 if ConditionPassed() then
5157 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5158 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5159 address = if index then offset_addr else R[n];
5160 R[t] = ZeroExtend(MemU[address,1], 32);
5161 if wback then R[n] = offset_addr;
5162#endif
5163
5164 bool success = false;
5165 const uint32_t opcode = OpcodeAsUnsigned (&success);
5166 if (!success)
5167 return false;
5168
5169 if (ConditionPassed ())
5170 {
5171 uint32_t t;
5172 uint32_t n;
5173 uint32_t imm32;
5174 bool index;
5175 bool add;
5176 bool wback;
5177
5178 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5179 switch (encoding)
5180 {
5181 case eEncodingT1:
5182 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5183 t = Bits32 (opcode, 2, 0);
5184 n = Bits32 (opcode, 5, 3);
5185 imm32 = Bits32 (opcode, 10, 6);
5186
5187 // index = TRUE; add = TRUE; wback = FALSE;
5188 index = true;
5189 add = true;
5190 wback= false;
5191
5192 break;
5193
5194 case eEncodingT2:
5195 // if Rt == ’1111’ then SEE PLD;
5196 // if Rn == ’1111’ then SEE LDRB (literal);
5197 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5198 t = Bits32 (opcode, 15, 12);
5199 n = Bits32 (opcode, 19, 16);
5200 imm32 = Bits32 (opcode, 11, 0);
5201
5202 // index = TRUE; add = TRUE; wback = FALSE;
5203 index = true;
5204 add = true;
5205 wback = false;
5206
5207 // if t == 13 then UNPREDICTABLE;
5208 if (t == 13)
5209 return false;
5210
5211 break;
5212
5213 case eEncodingT3:
5214 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5215 // if Rn == ’1111’ then SEE LDRB (literal);
5216 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5217 // if P == ’0’ && W == ’0’ then UNDEFINED;
5218 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5219 return false;
5220
5221 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5222 t = Bits32 (opcode, 15, 12);
5223 n = Bits32 (opcode, 19, 16);
5224 imm32 = Bits32 (opcode, 7, 0);
5225
5226 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5227 index = BitIsSet (opcode, 10);
5228 add = BitIsSet (opcode, 9);
5229 wback = BitIsSet (opcode, 8);
5230
5231 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5232 if (BadReg (t) || (wback && (n == t)))
5233 return false;
5234
5235 break;
5236
5237 default:
5238 return false;
5239 }
5240
5241 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5242 if (!success)
5243 return false;
5244
5245 addr_t address;
5246 addr_t offset_addr;
5247
5248 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5249 if (add)
5250 offset_addr = Rn + imm32;
5251 else
5252 offset_addr = Rn - imm32;
5253
5254 // address = if index then offset_addr else R[n];
5255 if (index)
5256 address = offset_addr;
5257 else
5258 address = Rn;
5259
5260 // R[t] = ZeroExtend(MemU[address,1], 32);
5261 Register base_reg;
5262 Register data_reg;
5263 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5264 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5265
5266 EmulateInstruction::Context context;
5267 context.type = eContextRegisterLoad;
5268 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5269
5270 uint64_t data = MemURead (context, address, 1, 0, &success);
5271 if (!success)
5272 return false;
5273
5274 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5275 return false;
5276
5277 // if wback then R[n] = offset_addr;
5278 if (wback)
5279 {
5280 context.type = eContextAdjustBaseRegister;
5281 context.SetAddress (offset_addr);
5282 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5283 return false;
5284 }
5285 }
5286 return true;
5287}
Caroline Ticef55261f2011-02-18 22:24:22 +00005288
5289// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5290// zero-extends it to form a 32-bit word and writes it to a register.
5291bool
5292EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5293{
5294#if 0
5295 if ConditionPassed() then
5296 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5297 base = Align(PC,4);
5298 address = if add then (base + imm32) else (base - imm32);
5299 R[t] = ZeroExtend(MemU[address,1], 32);
5300#endif
5301
5302 bool success = false;
5303 const uint32_t opcode = OpcodeAsUnsigned (&success);
5304 if (!success)
5305 return false;
5306
5307 if (ConditionPassed ())
5308 {
5309 uint32_t t;
5310 uint32_t imm32;
5311 bool add;
5312 switch (encoding)
5313 {
5314 case eEncodingT1:
5315 // if Rt == ’1111’ then SEE PLD;
5316 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5317 t = Bits32 (opcode, 15, 12);
5318 imm32 = Bits32 (opcode, 11, 0);
5319 add = BitIsSet (opcode, 23);
5320
5321 // if t == 13 then UNPREDICTABLE;
5322 if (t == 13)
5323 return false;
5324
5325 break;
5326
5327 case eEncodingA1:
5328 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5329 t = Bits32 (opcode, 15, 12);
5330 imm32 = Bits32 (opcode, 11, 0);
5331 add = BitIsSet (opcode, 23);
5332
5333 // if t == 15 then UNPREDICTABLE;
5334 if (t == 15)
5335 return false;
5336 break;
5337
5338 default:
5339 return false;
5340 }
5341
5342 // base = Align(PC,4);
5343 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5344 if (!success)
5345 return false;
5346
5347 uint32_t base = AlignPC (pc_val);
5348
5349 addr_t address;
5350 // address = if add then (base + imm32) else (base - imm32);
5351 if (add)
5352 address = base + imm32;
5353 else
5354 address = base - imm32;
5355
5356 // R[t] = ZeroExtend(MemU[address,1], 32);
5357 EmulateInstruction::Context context;
5358 context.type = eContextRelativeBranchImmediate;
5359 context.SetImmediate (address - base);
5360
5361 uint64_t data = MemURead (context, address, 1, 0, &success);
5362 if (!success)
5363 return false;
5364
5365 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5366 return false;
5367 }
5368 return true;
5369}
Caroline Tice30fec122011-02-18 23:52:21 +00005370
5371// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5372// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5373// optionally be shifted.
5374bool
5375EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5376{
5377#if 0
5378 if ConditionPassed() then
5379 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5380 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5381 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5382 address = if index then offset_addr else R[n];
5383 R[t] = ZeroExtend(MemU[address,1],32);
5384 if wback then R[n] = offset_addr;
5385#endif
5386
5387 bool success = false;
5388 const uint32_t opcode = OpcodeAsUnsigned (&success);
5389 if (!success)
5390 return false;
5391
5392 if (ConditionPassed ())
5393 {
5394 uint32_t t;
5395 uint32_t n;
5396 uint32_t m;
5397 bool index;
5398 bool add;
5399 bool wback;
5400 ARM_ShifterType shift_t;
5401 uint32_t shift_n;
5402
5403 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5404 switch (encoding)
5405 {
5406 case eEncodingT1:
5407 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5408 t = Bits32 (opcode, 2, 0);
5409 n = Bits32 (opcode, 5, 3);
5410 m = Bits32 (opcode, 8, 6);
5411
5412 // index = TRUE; add = TRUE; wback = FALSE;
5413 index = true;
5414 add = true;
5415 wback = false;
5416
5417 // (shift_t, shift_n) = (SRType_LSL, 0);
5418 shift_t = SRType_LSL;
5419 shift_n = 0;
5420 break;
5421
5422 case eEncodingT2:
5423 // if Rt == ’1111’ then SEE PLD;
5424 // if Rn == ’1111’ then SEE LDRB (literal);
5425 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5426 t = Bits32 (opcode, 15, 12);
5427 n = Bits32 (opcode, 19, 16);
5428 m = Bits32 (opcode, 3, 0);
5429
5430 // index = TRUE; add = TRUE; wback = FALSE;
5431 index = true;
5432 add = true;
5433 wback = false;
5434
5435 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5436 shift_t = SRType_LSL;
5437 shift_n = Bits32 (opcode, 5, 4);
5438
5439 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5440 if ((t == 13) || BadReg (m))
5441 return false;
5442 break;
5443
5444 case eEncodingA1:
5445 {
5446 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5447 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5448 t = Bits32 (opcode, 15, 12);
5449 n = Bits32 (opcode, 19, 16);
5450 m = Bits32 (opcode, 3, 0);
5451
5452 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5453 index = BitIsSet (opcode, 24);
5454 add = BitIsSet (opcode, 23);
5455 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5456
5457 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5458 uint32_t type = Bits32 (opcode, 6, 5);
5459 uint32_t imm5 = Bits32 (opcode, 11, 7);
5460 shift_n = DecodeImmShift (type, imm5, shift_t);
5461
5462 // if t == 15 || m == 15 then UNPREDICTABLE;
5463 if ((t == 15) || (m == 15))
5464 return false;
5465
5466 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5467 if (wback && ((n == 15) || (n == t)))
5468 return false;
5469 }
5470 break;
5471
5472 default:
5473 return false;
5474 }
5475
5476 addr_t offset_addr;
5477 addr_t address;
5478
5479 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5480 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5481 if (!success)
5482 return false;
5483
5484 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5485
5486 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5487 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5488 if (!success)
5489 return false;
5490
5491 if (add)
5492 offset_addr = Rn + offset;
5493 else
5494 offset_addr = Rn - offset;
5495
5496 // address = if index then offset_addr else R[n];
5497 if (index)
5498 address = offset_addr;
5499 else
5500 address = Rn;
5501
5502 // R[t] = ZeroExtend(MemU[address,1],32);
5503 Register base_reg;
5504 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5505
5506 EmulateInstruction::Context context;
5507 context.type = eContextRegisterLoad;
5508 context.SetRegisterPlusOffset (base_reg, address - Rn);
5509
5510 uint64_t data = MemURead (context, address, 1, 0, &success);
5511 if (!success)
5512 return false;
5513
5514 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5515 return false;
5516
5517 // if wback then R[n] = offset_addr;
5518 if (wback)
5519 {
5520 context.type = eContextAdjustBaseRegister;
5521 context.SetAddress (offset_addr);
5522 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5523 return false;
5524 }
5525 }
5526 return true;
5527}
Caroline Ticefe479112011-02-18 18:52:37 +00005528
Johnny Chen2115b412011-02-21 23:42:44 +00005529// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
5530// and writes the result to the destination register. It can optionally update the condition flags based on
5531// the result.
5532bool
5533EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
5534{
5535#if 0
5536 // ARM pseudo code...
5537 if ConditionPassed() then
5538 EncodingSpecificOperations();
5539 result = R[n] EOR imm32;
5540 if d == 15 then // Can only occur for ARM encoding
5541 ALUWritePC(result); // setflags is always FALSE here
5542 else
5543 R[d] = result;
5544 if setflags then
5545 APSR.N = result<31>;
5546 APSR.Z = IsZeroBit(result);
5547 APSR.C = carry;
5548 // APSR.V unchanged
5549#endif
5550
5551 bool success = false;
5552 const uint32_t opcode = OpcodeAsUnsigned (&success);
5553 if (!success)
5554 return false;
5555
5556 if (ConditionPassed())
5557 {
5558 uint32_t Rd, Rn;
5559 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5560 bool setflags;
5561 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5562 switch (encoding)
5563 {
5564 case eEncodingT1:
5565 Rd = Bits32(opcode, 11, 8);
5566 Rn = Bits32(opcode, 19, 16);
5567 setflags = BitIsSet(opcode, 20);
5568 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5569 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
5570 if (Rd == 15 && setflags)
5571 return EmulateTEQImm(eEncodingT1);
5572 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5573 return false;
5574 break;
5575 case eEncodingA1:
5576 Rd = Bits32(opcode, 15, 12);
5577 Rn = Bits32(opcode, 19, 16);
5578 setflags = BitIsSet(opcode, 20);
5579 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5580 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5581 // TODO: Emulate SUBS PC, LR and related instructions.
5582 if (Rd == 15 && setflags)
5583 return false;
5584 break;
5585 default:
5586 return false;
5587 }
5588
5589 // Read the first operand.
5590 uint32_t val1 = ReadCoreReg(Rn, &success);
5591 if (!success)
5592 return false;
5593
5594 uint32_t result = val1 ^ imm32;
5595
5596 EmulateInstruction::Context context;
5597 context.type = EmulateInstruction::eContextImmediate;
5598 context.SetNoArgs ();
5599
5600 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5601 return false;
5602 }
5603 return true;
5604}
5605
5606// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
5607// optionally-shifted register value, and writes the result to the destination register.
5608// It can optionally update the condition flags based on the result.
5609bool
5610EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
5611{
5612#if 0
5613 // ARM pseudo code...
5614 if ConditionPassed() then
5615 EncodingSpecificOperations();
5616 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5617 result = R[n] EOR shifted;
5618 if d == 15 then // Can only occur for ARM encoding
5619 ALUWritePC(result); // setflags is always FALSE here
5620 else
5621 R[d] = result;
5622 if setflags then
5623 APSR.N = result<31>;
5624 APSR.Z = IsZeroBit(result);
5625 APSR.C = carry;
5626 // APSR.V unchanged
5627#endif
5628
5629 bool success = false;
5630 const uint32_t opcode = OpcodeAsUnsigned (&success);
5631 if (!success)
5632 return false;
5633
5634 if (ConditionPassed())
5635 {
5636 uint32_t Rd, Rn, Rm;
5637 ARM_ShifterType shift_t;
5638 uint32_t shift_n; // the shift applied to the value read from Rm
5639 bool setflags;
5640 uint32_t carry;
5641 switch (encoding)
5642 {
5643 case eEncodingT1:
5644 Rd = Rn = Bits32(opcode, 2, 0);
5645 Rm = Bits32(opcode, 5, 3);
5646 setflags = !InITBlock();
5647 shift_t = SRType_LSL;
5648 shift_n = 0;
5649 case eEncodingT2:
5650 Rd = Bits32(opcode, 11, 8);
5651 Rn = Bits32(opcode, 19, 16);
5652 Rm = Bits32(opcode, 3, 0);
5653 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005654 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5655 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00005656 if (Rd == 15 && setflags)
5657 return EmulateTEQReg(eEncodingT1);
5658 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5659 return false;
5660 break;
5661 case eEncodingA1:
5662 Rd = Bits32(opcode, 15, 12);
5663 Rn = Bits32(opcode, 19, 16);
5664 Rm = Bits32(opcode, 3, 0);
5665 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005666 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005667 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5668 // TODO: Emulate SUBS PC, LR and related instructions.
5669 if (Rd == 15 && setflags)
5670 return false;
5671 break;
5672 default:
5673 return false;
5674 }
5675
5676 // Read the first operand.
5677 uint32_t val1 = ReadCoreReg(Rn, &success);
5678 if (!success)
5679 return false;
5680
5681 // Read the second operand.
5682 uint32_t val2 = ReadCoreReg(Rm, &success);
5683 if (!success)
5684 return false;
5685
5686 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5687 uint32_t result = val1 ^ shifted;
5688
5689 EmulateInstruction::Context context;
5690 context.type = EmulateInstruction::eContextImmediate;
5691 context.SetNoArgs ();
5692
5693 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5694 return false;
5695 }
5696 return true;
5697}
5698
Johnny Chen7c5234d2011-02-18 23:41:11 +00005699// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5700// writes the result to the destination register. It can optionally update the condition flags based
5701// on the result.
5702bool
5703EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5704{
5705#if 0
5706 // ARM pseudo code...
5707 if ConditionPassed() then
5708 EncodingSpecificOperations();
5709 result = R[n] OR imm32;
5710 if d == 15 then // Can only occur for ARM encoding
5711 ALUWritePC(result); // setflags is always FALSE here
5712 else
5713 R[d] = result;
5714 if setflags then
5715 APSR.N = result<31>;
5716 APSR.Z = IsZeroBit(result);
5717 APSR.C = carry;
5718 // APSR.V unchanged
5719#endif
5720
5721 bool success = false;
5722 const uint32_t opcode = OpcodeAsUnsigned (&success);
5723 if (!success)
5724 return false;
5725
5726 if (ConditionPassed())
5727 {
5728 uint32_t Rd, Rn;
5729 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5730 bool setflags;
5731 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5732 switch (encoding)
5733 {
5734 case eEncodingT1:
5735 Rd = Bits32(opcode, 11, 8);
5736 Rn = Bits32(opcode, 19, 16);
5737 setflags = BitIsSet(opcode, 20);
5738 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5739 // if Rn == ‘1111’ then SEE MOV (immediate);
5740 if (Rn == 15)
5741 return EmulateMOVRdImm(eEncodingT2);
5742 if (BadReg(Rd) || Rn == 13)
5743 return false;
5744 break;
5745 case eEncodingA1:
5746 Rd = Bits32(opcode, 15, 12);
5747 Rn = Bits32(opcode, 19, 16);
5748 setflags = BitIsSet(opcode, 20);
5749 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5750 // TODO: Emulate SUBS PC, LR and related instructions.
5751 if (Rd == 15 && setflags)
5752 return false;
5753 break;
5754 default:
5755 return false;
5756 }
5757
5758 // Read the first operand.
5759 uint32_t val1 = ReadCoreReg(Rn, &success);
5760 if (!success)
5761 return false;
5762
5763 uint32_t result = val1 | imm32;
5764
5765 EmulateInstruction::Context context;
5766 context.type = EmulateInstruction::eContextImmediate;
5767 context.SetNoArgs ();
5768
5769 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5770 return false;
5771 }
5772 return true;
5773}
5774
5775// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5776// value, and writes the result to the destination register. It can optionally update the condition flags based
5777// on the result.
5778bool
5779EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5780{
5781#if 0
5782 // ARM pseudo code...
5783 if ConditionPassed() then
5784 EncodingSpecificOperations();
5785 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5786 result = R[n] OR shifted;
5787 if d == 15 then // Can only occur for ARM encoding
5788 ALUWritePC(result); // setflags is always FALSE here
5789 else
5790 R[d] = result;
5791 if setflags then
5792 APSR.N = result<31>;
5793 APSR.Z = IsZeroBit(result);
5794 APSR.C = carry;
5795 // APSR.V unchanged
5796#endif
5797
5798 bool success = false;
5799 const uint32_t opcode = OpcodeAsUnsigned (&success);
5800 if (!success)
5801 return false;
5802
5803 if (ConditionPassed())
5804 {
5805 uint32_t Rd, Rn, Rm;
5806 ARM_ShifterType shift_t;
5807 uint32_t shift_n; // the shift applied to the value read from Rm
5808 bool setflags;
5809 uint32_t carry;
5810 switch (encoding)
5811 {
5812 case eEncodingT1:
5813 Rd = Rn = Bits32(opcode, 2, 0);
5814 Rm = Bits32(opcode, 5, 3);
5815 setflags = !InITBlock();
5816 shift_t = SRType_LSL;
5817 shift_n = 0;
5818 case eEncodingT2:
5819 Rd = Bits32(opcode, 11, 8);
5820 Rn = Bits32(opcode, 19, 16);
5821 Rm = Bits32(opcode, 3, 0);
5822 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005823 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5824 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005825 if (Rn == 15)
5826 return EmulateMOVRdRm(eEncodingT3);
5827 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5828 return false;
5829 break;
5830 case eEncodingA1:
5831 Rd = Bits32(opcode, 15, 12);
5832 Rn = Bits32(opcode, 19, 16);
5833 Rm = Bits32(opcode, 3, 0);
5834 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005835 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00005836 // TODO: Emulate SUBS PC, LR and related instructions.
5837 if (Rd == 15 && setflags)
5838 return false;
5839 break;
5840 default:
5841 return false;
5842 }
5843
5844 // Read the first operand.
5845 uint32_t val1 = ReadCoreReg(Rn, &success);
5846 if (!success)
5847 return false;
5848
5849 // Read the second operand.
5850 uint32_t val2 = ReadCoreReg(Rm, &success);
5851 if (!success)
5852 return false;
5853
5854 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00005855 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00005856
5857 EmulateInstruction::Context context;
5858 context.type = EmulateInstruction::eContextImmediate;
5859 context.SetNoArgs ();
5860
5861 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5862 return false;
5863 }
5864 return true;
5865}
5866
Johnny Chen2115b412011-02-21 23:42:44 +00005867// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
5868// immediate value. It updates the condition flags based on the result, and discards the result.
5869bool
5870EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
5871{
5872#if 0
5873 // ARM pseudo code...
5874 if ConditionPassed() then
5875 EncodingSpecificOperations();
5876 result = R[n] EOR imm32;
5877 APSR.N = result<31>;
5878 APSR.Z = IsZeroBit(result);
5879 APSR.C = carry;
5880 // APSR.V unchanged
5881#endif
5882
5883 bool success = false;
5884 const uint32_t opcode = OpcodeAsUnsigned (&success);
5885 if (!success)
5886 return false;
5887
5888 if (ConditionPassed())
5889 {
5890 uint32_t Rn;
5891 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5892 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5893 switch (encoding)
5894 {
5895 case eEncodingT1:
5896 Rn = Bits32(opcode, 19, 16);
5897 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5898 if (BadReg(Rn))
5899 return false;
5900 break;
5901 case eEncodingA1:
5902 Rn = Bits32(opcode, 19, 16);
5903 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5904 break;
5905 default:
5906 return false;
5907 }
5908
5909 // Read the first operand.
5910 uint32_t val1 = ReadCoreReg(Rn, &success);
5911 if (!success)
5912 return false;
5913
5914 uint32_t result = val1 ^ imm32;
5915
5916 EmulateInstruction::Context context;
5917 context.type = EmulateInstruction::eContextImmediate;
5918 context.SetNoArgs ();
5919
5920 if (!WriteFlags(context, result, carry))
5921 return false;
5922 }
5923 return true;
5924}
5925
5926// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
5927// optionally-shifted register value. It updates the condition flags based on the result, and discards
5928// the result.
5929bool
5930EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
5931{
5932#if 0
5933 // ARM pseudo code...
5934 if ConditionPassed() then
5935 EncodingSpecificOperations();
5936 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5937 result = R[n] EOR shifted;
5938 APSR.N = result<31>;
5939 APSR.Z = IsZeroBit(result);
5940 APSR.C = carry;
5941 // APSR.V unchanged
5942#endif
5943
5944 bool success = false;
5945 const uint32_t opcode = OpcodeAsUnsigned (&success);
5946 if (!success)
5947 return false;
5948
5949 if (ConditionPassed())
5950 {
5951 uint32_t Rn, Rm;
5952 ARM_ShifterType shift_t;
5953 uint32_t shift_n; // the shift applied to the value read from Rm
5954 uint32_t carry;
5955 switch (encoding)
5956 {
5957 case eEncodingT1:
5958 Rn = Bits32(opcode, 19, 16);
5959 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00005960 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005961 if (BadReg(Rn) || BadReg(Rm))
5962 return false;
5963 break;
5964 case eEncodingA1:
5965 Rn = Bits32(opcode, 19, 16);
5966 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00005967 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00005968 break;
5969 default:
5970 return false;
5971 }
5972
5973 // Read the first operand.
5974 uint32_t val1 = ReadCoreReg(Rn, &success);
5975 if (!success)
5976 return false;
5977
5978 // Read the second operand.
5979 uint32_t val2 = ReadCoreReg(Rm, &success);
5980 if (!success)
5981 return false;
5982
5983 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5984 uint32_t result = val1 ^ shifted;
5985
5986 EmulateInstruction::Context context;
5987 context.type = EmulateInstruction::eContextImmediate;
5988 context.SetNoArgs ();
5989
5990 if (!WriteFlags(context, result, carry))
5991 return false;
5992 }
5993 return true;
5994}
5995
Johnny Chende3cce32011-02-21 21:24:49 +00005996// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
5997// It updates the condition flags based on the result, and discards the result.
5998bool
5999EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
6000{
6001#if 0
6002 // ARM pseudo code...
6003 if ConditionPassed() then
6004 EncodingSpecificOperations();
6005 result = R[n] AND imm32;
6006 APSR.N = result<31>;
6007 APSR.Z = IsZeroBit(result);
6008 APSR.C = carry;
6009 // APSR.V unchanged
6010#endif
6011
6012 bool success = false;
6013 const uint32_t opcode = OpcodeAsUnsigned (&success);
6014 if (!success)
6015 return false;
6016
6017 if (ConditionPassed())
6018 {
6019 uint32_t Rn;
6020 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
6021 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6022 switch (encoding)
6023 {
6024 case eEncodingT1:
6025 Rn = Bits32(opcode, 19, 16);
6026 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6027 if (BadReg(Rn))
6028 return false;
6029 break;
6030 case eEncodingA1:
6031 Rn = Bits32(opcode, 19, 16);
6032 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6033 break;
6034 default:
6035 return false;
6036 }
6037
6038 // Read the first operand.
6039 uint32_t val1 = ReadCoreReg(Rn, &success);
6040 if (!success)
6041 return false;
6042
6043 uint32_t result = val1 & imm32;
6044
6045 EmulateInstruction::Context context;
6046 context.type = EmulateInstruction::eContextImmediate;
6047 context.SetNoArgs ();
6048
6049 if (!WriteFlags(context, result, carry))
6050 return false;
6051 }
6052 return true;
6053}
6054
6055// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
6056// It updates the condition flags based on the result, and discards the result.
6057bool
6058EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
6059{
6060#if 0
6061 // ARM pseudo code...
6062 if ConditionPassed() then
6063 EncodingSpecificOperations();
6064 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6065 result = R[n] AND shifted;
6066 APSR.N = result<31>;
6067 APSR.Z = IsZeroBit(result);
6068 APSR.C = carry;
6069 // APSR.V unchanged
6070#endif
6071
6072 bool success = false;
6073 const uint32_t opcode = OpcodeAsUnsigned (&success);
6074 if (!success)
6075 return false;
6076
6077 if (ConditionPassed())
6078 {
6079 uint32_t Rn, Rm;
6080 ARM_ShifterType shift_t;
6081 uint32_t shift_n; // the shift applied to the value read from Rm
6082 uint32_t carry;
6083 switch (encoding)
6084 {
6085 case eEncodingT1:
6086 Rn = Bits32(opcode, 2, 0);
6087 Rm = Bits32(opcode, 5, 3);
6088 shift_t = SRType_LSL;
6089 shift_n = 0;
6090 case eEncodingT2:
6091 Rn = Bits32(opcode, 19, 16);
6092 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006093 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006094 if (BadReg(Rn) || BadReg(Rm))
6095 return false;
6096 break;
6097 case eEncodingA1:
6098 Rn = Bits32(opcode, 19, 16);
6099 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00006100 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00006101 break;
6102 default:
6103 return false;
6104 }
6105
6106 // Read the first operand.
6107 uint32_t val1 = ReadCoreReg(Rn, &success);
6108 if (!success)
6109 return false;
6110
6111 // Read the second operand.
6112 uint32_t val2 = ReadCoreReg(Rm, &success);
6113 if (!success)
6114 return false;
6115
6116 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6117 uint32_t result = val1 & shifted;
6118
6119 EmulateInstruction::Context context;
6120 context.type = EmulateInstruction::eContextImmediate;
6121 context.SetNoArgs ();
6122
6123 if (!WriteFlags(context, result, carry))
6124 return false;
6125 }
6126 return true;
6127}
6128
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006129EmulateInstructionARM::ARMOpcode*
6130EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00006131{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006132 static ARMOpcode
6133 g_arm_opcodes[] =
6134 {
6135 //----------------------------------------------------------------------
6136 // Prologue instructions
6137 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00006138
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006139 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006140 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6141 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00006142
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006143 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006144 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006145 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00006146 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00006147 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
6148 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00006149 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00006150
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006151 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006152 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00006153
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006154 // push one register
6155 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00006156 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00006157
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006158 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00006159 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6160 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00006161
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006162 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00006163 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006164 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00006165
Johnny Chen9f687722011-02-18 00:02:28 +00006166 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6167 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00006168 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006169 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
6170
6171 //----------------------------------------------------------------------
6172 // Supervisor Call (previously Software Interrupt)
6173 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006174 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
6175
6176 //----------------------------------------------------------------------
6177 // Branch instructions
6178 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006179 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00006180 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
6181 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6182 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6183 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006184 // for example, "bx lr"
6185 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006186
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006187 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00006188 // Data-processing instructions
6189 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006190 // adc (immediate)
6191 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
6192 // adc (register)
6193 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006194 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006195 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00006196 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006197 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006198 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006199 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006200 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00006201 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006202 // eor (immediate)
6203 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
6204 // eor (register)
6205 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006206 // orr (immediate)
6207 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
6208 // orr (register)
6209 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006210 // teq (immediate)
6211 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
6212 // teq (register)
6213 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006214 // tst (immediate)
6215 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
6216 // tst (register)
6217 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
6218
6219
Johnny Chend642a6a2011-02-22 01:01:03 +00006220 // mvn (immediate)
6221 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
6222 // mvn (register)
6223 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00006224 // cmn (immediate)
6225 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
6226 // cmn (register)
6227 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006228 // cmp (immediate)
6229 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
6230 // cmp (register)
6231 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006232 // asr (immediate)
6233 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006234 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00006235 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006236 // lsl (immediate)
6237 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
6238 // lsl (register)
6239 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
6240 // lsr (immediate)
6241 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
6242 // lsr (register)
6243 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006244 // rrx is a special case encoding of ror (immediate)
6245 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
6246 // ror (immediate)
6247 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
6248 // ror (register)
6249 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00006250
6251 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006252 // Load instructions
6253 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00006254 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00006255 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00006256 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00006257 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00006258 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00006259 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00006260 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
6261 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00006262
6263 //----------------------------------------------------------------------
6264 // Store instructions
6265 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00006266 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006267 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00006268 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00006269 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
6270 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00006271
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006272
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006273 };
6274 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
6275
6276 for (size_t i=0; i<k_num_arm_opcodes; ++i)
6277 {
6278 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
6279 return &g_arm_opcodes[i];
6280 }
6281 return NULL;
6282}
Greg Clayton64c84432011-01-21 22:02:52 +00006283
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006284
6285EmulateInstructionARM::ARMOpcode*
6286EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00006287{
Johnny Chenfdd179e2011-01-31 20:09:28 +00006288
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006289 static ARMOpcode
6290 g_thumb_opcodes[] =
6291 {
6292 //----------------------------------------------------------------------
6293 // Prologue instructions
6294 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00006295
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006296 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00006297 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
6298 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
6299 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00006300
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006301 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00006302 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006303 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00006304 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00006305 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00006306 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00006307
Johnny Chen864a8e82011-02-18 00:07:39 +00006308 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00006309 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00006310
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006311 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00006312 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
6313 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
6314 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
6315 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006316
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006317 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00006318 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
6319 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00006320
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006321 //----------------------------------------------------------------------
6322 // Epilogue instructions
6323 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00006324
Johnny Chen864a8e82011-02-18 00:07:39 +00006325 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00006326 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
6327 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
6328 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00006329 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
6330 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00006331
6332 //----------------------------------------------------------------------
6333 // Supervisor Call (previously Software Interrupt)
6334 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00006335 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
6336
6337 //----------------------------------------------------------------------
6338 // If Then makes up to four following instructions conditional.
6339 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00006340 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
6341
6342 //----------------------------------------------------------------------
6343 // Branch instructions
6344 //----------------------------------------------------------------------
6345 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
6346 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
6347 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00006348 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006349 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00006350 // J1 == J2 == 1
6351 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
6352 // J1 == J2 == 1
6353 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
6354 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00006355 // for example, "bx lr"
6356 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00006357 // compare and branch
6358 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00006359 // table branch byte
6360 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
6361 // table branch halfword
6362 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006363
6364 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00006365 // Data-processing instructions
6366 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00006367 // adc (immediate)
6368 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
6369 // adc (register)
6370 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
6371 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
6372 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00006373 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006374 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00006375 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006376 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00006377 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00006378 // and (register)
6379 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
6380 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006381 // eor (immediate)
6382 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
6383 // eor (register)
6384 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
6385 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006386 // orr (immediate)
6387 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
6388 // orr (register)
6389 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
6390 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00006391 // teq (immediate)
6392 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
6393 // teq (register)
6394 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00006395 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00006396 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00006397 // tst (register)
6398 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
6399 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
6400
Johnny Chen7c5234d2011-02-18 23:41:11 +00006401
Johnny Chen338bf542011-02-10 19:29:03 +00006402 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00006403 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00006404 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00006405 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00006406 // mov{s}<c>.w <Rd>, <Rm>
6407 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00006408 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00006409 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
6410 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00006411 // mvn (immediate)
6412 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
6413 // mvn (register)
6414 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
6415 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006416 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00006417 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006418 // cmn (register)
6419 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006420 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006421 // cmp (immediate)
6422 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00006423 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00006424 // cmp (register) (Rn and Rm both from r0-r7)
6425 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
6426 // cmp (register) (Rn and Rm not both from r0-r7)
6427 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00006428 // asr (immediate)
6429 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00006430 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00006431 // asr (register)
6432 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
6433 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006434 // lsl (immediate)
6435 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
6436 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
6437 // lsl (register)
6438 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
6439 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
6440 // lsr (immediate)
6441 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
6442 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
6443 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00006444 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00006445 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00006446 // rrx is a special case encoding of ror (immediate)
6447 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
6448 // ror (immediate)
6449 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
6450 // ror (register)
6451 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
6452 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00006453
6454 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00006455 // Load instructions
6456 //----------------------------------------------------------------------
6457 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00006458 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00006459 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00006460 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
6461 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00006462 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00006463 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
6464 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00006465 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
6466 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
6467 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00006468 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00006469 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
6470 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00006471
6472 //----------------------------------------------------------------------
6473 // Store instructions
6474 //----------------------------------------------------------------------
6475 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00006476 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00006477 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00006478 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
6479 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
6480 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
6481 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
6482 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
6483 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
6484 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
6485 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
6486 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00006487 };
6488
6489 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
6490 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
6491 {
6492 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
6493 return &g_thumb_opcodes[i];
6494 }
6495 return NULL;
6496}
Greg Clayton64c84432011-01-21 22:02:52 +00006497
Greg Clayton31e2a382011-01-30 20:03:56 +00006498bool
Greg Clayton395fc332011-02-15 21:59:32 +00006499EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00006500{
6501 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00006502 const char *arch_cstr = arch.AsCString ();
6503 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00006504 {
Greg Clayton395fc332011-02-15 21:59:32 +00006505 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
6506 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
6507 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
6508 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
6509 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
6510 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
6511 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
6512 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
6513 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
6514 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00006515 }
6516 return m_arm_isa != 0;
6517}
6518
6519
Greg Clayton64c84432011-01-21 22:02:52 +00006520bool
6521EmulateInstructionARM::ReadInstruction ()
6522{
6523 bool success = false;
6524 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
6525 if (success)
6526 {
6527 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
6528 if (success)
6529 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00006530 Context read_inst_context;
6531 read_inst_context.type = eContextReadOpcode;
6532 read_inst_context.SetNoArgs ();
6533
Greg Clayton64c84432011-01-21 22:02:52 +00006534 if (m_inst_cpsr & MASK_CPSR_T)
6535 {
6536 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006537 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006538
6539 if (success)
6540 {
6541 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
6542 {
6543 m_inst.opcode_type = eOpcode16;
6544 m_inst.opcode.inst16 = thumb_opcode;
6545 }
6546 else
6547 {
6548 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006549 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006550 }
6551 }
6552 }
6553 else
6554 {
6555 m_inst_mode = eModeARM;
6556 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00006557 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00006558 }
6559 }
6560 }
6561 if (!success)
6562 {
6563 m_inst_mode = eModeInvalid;
6564 m_inst_pc = LLDB_INVALID_ADDRESS;
6565 }
6566 return success;
6567}
6568
Johnny Chenee9b1f72011-02-09 01:00:31 +00006569uint32_t
6570EmulateInstructionARM::ArchVersion ()
6571{
6572 return m_arm_isa;
6573}
6574
Greg Clayton64c84432011-01-21 22:02:52 +00006575bool
6576EmulateInstructionARM::ConditionPassed ()
6577{
6578 if (m_inst_cpsr == 0)
6579 return false;
6580
6581 const uint32_t cond = CurrentCond ();
6582
6583 if (cond == UINT32_MAX)
6584 return false;
6585
6586 bool result = false;
6587 switch (UnsignedBits(cond, 3, 1))
6588 {
6589 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
6590 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
6591 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
6592 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
6593 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
6594 case 5:
6595 {
6596 bool n = (m_inst_cpsr & MASK_CPSR_N);
6597 bool v = (m_inst_cpsr & MASK_CPSR_V);
6598 result = n == v;
6599 }
6600 break;
6601 case 6:
6602 {
6603 bool n = (m_inst_cpsr & MASK_CPSR_N);
6604 bool v = (m_inst_cpsr & MASK_CPSR_V);
6605 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
6606 }
6607 break;
6608 case 7:
6609 result = true;
6610 break;
6611 }
6612
6613 if (cond & 1)
6614 result = !result;
6615 return result;
6616}
6617
Johnny Chen9ee056b2011-02-08 00:06:35 +00006618uint32_t
6619EmulateInstructionARM::CurrentCond ()
6620{
6621 switch (m_inst_mode)
6622 {
6623 default:
6624 case eModeInvalid:
6625 break;
6626
6627 case eModeARM:
6628 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
6629
6630 case eModeThumb:
6631 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
6632 // 'cond' field of the encoding.
6633 if (m_inst.opcode_type == eOpcode16 &&
6634 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
6635 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
6636 {
6637 return Bits32(m_inst.opcode.inst16, 11, 7);
6638 }
6639 else if (m_inst.opcode_type == eOpcode32 &&
6640 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
6641 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
6642 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
6643 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
6644 {
6645 return Bits32(m_inst.opcode.inst32, 25, 22);
6646 }
6647
6648 return m_it_session.GetCond();
6649 }
6650 return UINT32_MAX; // Return invalid value
6651}
6652
Johnny Chen9ee056b2011-02-08 00:06:35 +00006653bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00006654EmulateInstructionARM::InITBlock()
6655{
6656 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
6657}
6658
6659bool
6660EmulateInstructionARM::LastInITBlock()
6661{
6662 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
6663}
6664
6665bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00006666EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
6667{
6668 addr_t target;
6669
Johnny Chenee9b1f72011-02-09 01:00:31 +00006670 // Check the current instruction set.
6671 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006672 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006673 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00006674 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006675
Johnny Chen9ee056b2011-02-08 00:06:35 +00006676 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006677 return false;
6678
6679 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006680}
6681
6682// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
6683bool
Johnny Chen668b4512011-02-15 21:08:58 +00006684EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00006685{
6686 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00006687 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
6688 // we want to record it and issue a WriteRegister callback so the clients
6689 // can track the mode changes accordingly.
6690 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006691
6692 if (BitIsSet(addr, 0))
6693 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006694 if (CurrentInstrSet() != eModeThumb)
6695 {
6696 SelectInstrSet(eModeThumb);
6697 cpsr_changed = true;
6698 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006699 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00006700 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006701 }
6702 else if (BitIsClear(addr, 1))
6703 {
Johnny Chen0f309db2011-02-09 19:11:32 +00006704 if (CurrentInstrSet() != eModeARM)
6705 {
6706 SelectInstrSet(eModeARM);
6707 cpsr_changed = true;
6708 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006709 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00006710 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00006711 }
6712 else
6713 return false; // address<1:0> == '10' => UNPREDICTABLE
6714
Johnny Chen0f309db2011-02-09 19:11:32 +00006715 if (cpsr_changed)
6716 {
Johnny Chen558133b2011-02-09 23:59:17 +00006717 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00006718 return false;
6719 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00006720 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00006721 return false;
6722
6723 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00006724}
Greg Clayton64c84432011-01-21 22:02:52 +00006725
Johnny Chenee9b1f72011-02-09 01:00:31 +00006726// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
6727bool
Johnny Chen668b4512011-02-15 21:08:58 +00006728EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00006729{
6730 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00006731 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00006732 else
6733 return BranchWritePC((const Context)context, addr);
6734}
6735
Johnny Chen26863dc2011-02-09 23:43:29 +00006736// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
6737bool
Johnny Chen668b4512011-02-15 21:08:58 +00006738EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00006739{
6740 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00006741 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00006742 else
6743 return BranchWritePC((const Context)context, addr);
6744}
6745
Johnny Chenee9b1f72011-02-09 01:00:31 +00006746EmulateInstructionARM::Mode
6747EmulateInstructionARM::CurrentInstrSet ()
6748{
6749 return m_inst_mode;
6750}
6751
6752// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00006753// ReadInstruction() is performed. This function has a side effect of updating
6754// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00006755bool
6756EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
6757{
Johnny Chen558133b2011-02-09 23:59:17 +00006758 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006759 switch (arm_or_thumb)
6760 {
6761 default:
6762 return false;
6763 eModeARM:
6764 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006765 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006766 break;
6767 eModeThumb:
6768 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00006769 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00006770 break;
6771 }
6772 return true;
6773}
6774
Johnny Chenef21b592011-02-10 01:52:38 +00006775// This function returns TRUE if the processor currently provides support for
6776// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
6777// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
6778bool
6779EmulateInstructionARM::UnalignedSupport()
6780{
6781 return (ArchVersion() >= ARMv7);
6782}
6783
Johnny Chenbf6ad172011-02-11 01:29:53 +00006784// The main addition and subtraction instructions can produce status information
6785// about both unsigned carry and signed overflow conditions. This status
6786// information can be used to synthesize multi-word additions and subtractions.
6787EmulateInstructionARM::AddWithCarryResult
6788EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
6789{
6790 uint32_t result;
6791 uint8_t carry_out;
6792 uint8_t overflow;
6793
6794 uint64_t unsigned_sum = x + y + carry_in;
6795 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
6796
6797 result = UnsignedBits(unsigned_sum, 31, 0);
6798 carry_out = (result == unsigned_sum ? 0 : 1);
6799 overflow = ((int32_t)result == signed_sum ? 0 : 1);
6800
6801 AddWithCarryResult res = { result, carry_out, overflow };
6802 return res;
6803}
6804
Johnny Chen157b9592011-02-18 21:13:05 +00006805uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00006806EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00006807{
Johnny Chene39f22d2011-02-19 01:36:13 +00006808 uint32_t reg_kind, reg_num;
6809 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00006810 {
Johnny Chene39f22d2011-02-19 01:36:13 +00006811 case SP_REG:
6812 reg_kind = eRegisterKindGeneric;
6813 reg_num = LLDB_REGNUM_GENERIC_SP;
6814 break;
6815 case LR_REG:
6816 reg_kind = eRegisterKindGeneric;
6817 reg_num = LLDB_REGNUM_GENERIC_RA;
6818 break;
6819 case PC_REG:
6820 reg_kind = eRegisterKindGeneric;
6821 reg_num = LLDB_REGNUM_GENERIC_PC;
6822 break;
6823 default:
6824 if (0 <= num && num < SP_REG)
6825 {
6826 reg_kind = eRegisterKindDWARF;
6827 reg_num = dwarf_r0 + num;
6828 }
Johnny Chen157b9592011-02-18 21:13:05 +00006829 else
Johnny Chene39f22d2011-02-19 01:36:13 +00006830 {
6831 assert(0 && "Invalid register number");
6832 *success = false;
6833 return ~0u;
6834 }
6835 break;
Johnny Chen157b9592011-02-18 21:13:05 +00006836 }
Johnny Chene39f22d2011-02-19 01:36:13 +00006837
6838 // Read our register.
6839 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
6840
6841 // When executing an ARM instruction , PC reads as the address of the current
6842 // instruction plus 8.
6843 // When executing a Thumb instruction , PC reads as the address of the current
6844 // instruction plus 4.
6845 if (num == 15)
6846 {
6847 if (CurrentInstrSet() == eModeARM)
6848 val += 8;
6849 else
6850 val += 4;
6851 }
Johnny Chen157b9592011-02-18 21:13:05 +00006852
6853 return val;
6854}
6855
Johnny Chenca67d1c2011-02-17 01:35:27 +00006856// Write the result to the ARM core register Rd, and optionally update the
6857// condition flags based on the result.
6858//
6859// This helper method tries to encapsulate the following pseudocode from the
6860// ARM Architecture Reference Manual:
6861//
6862// if d == 15 then // Can only occur for encoding A1
6863// ALUWritePC(result); // setflags is always FALSE here
6864// else
6865// R[d] = result;
6866// if setflags then
6867// APSR.N = result<31>;
6868// APSR.Z = IsZeroBit(result);
6869// APSR.C = carry;
6870// // APSR.V unchanged
6871//
6872// In the above case, the API client does not pass in the overflow arg, which
6873// defaults to ~0u.
6874bool
Johnny Chen10530c22011-02-17 22:37:12 +00006875EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
6876 const uint32_t result,
6877 const uint32_t Rd,
6878 bool setflags,
6879 const uint32_t carry,
6880 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00006881{
6882 if (Rd == 15)
6883 {
6884 if (!ALUWritePC (context, result))
6885 return false;
6886 }
6887 else
6888 {
6889 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
6890 return false;
6891 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00006892 return WriteFlags (context, result, carry, overflow);
6893 }
6894 return true;
6895}
6896
6897// This helper method tries to encapsulate the following pseudocode from the
6898// ARM Architecture Reference Manual:
6899//
6900// APSR.N = result<31>;
6901// APSR.Z = IsZeroBit(result);
6902// APSR.C = carry;
6903// APSR.V = overflow
6904//
6905// Default arguments can be specified for carry and overflow parameters, which means
6906// not to update the respective flags.
6907bool
6908EmulateInstructionARM::WriteFlags (Context &context,
6909 const uint32_t result,
6910 const uint32_t carry,
6911 const uint32_t overflow)
6912{
6913 m_new_inst_cpsr = m_inst_cpsr;
6914 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
6915 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
6916 if (carry != ~0u)
6917 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
6918 if (overflow != ~0u)
6919 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
6920 if (m_new_inst_cpsr != m_inst_cpsr)
6921 {
6922 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
6923 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00006924 }
6925 return true;
6926}
6927
Greg Clayton64c84432011-01-21 22:02:52 +00006928bool
6929EmulateInstructionARM::EvaluateInstruction ()
6930{
Johnny Chenc315f862011-02-05 00:46:10 +00006931 // Advance the ITSTATE bits to their values for the next instruction.
6932 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
6933 m_it_session.ITAdvance();
6934
Greg Clayton64c84432011-01-21 22:02:52 +00006935 return false;
6936}