blob: 4f163148bd29595fbba382b5a22adf7f3644eaea [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000133#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000134#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000135
Johnny Chen0e00af22011-02-10 19:40:42 +0000136//----------------------------------------------------------------------
137//
138// EmulateInstructionARM implementation
139//
140//----------------------------------------------------------------------
141
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142void
143EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000146
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000147void
148EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000149{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000150}
151
Caroline Ticefa172202011-02-11 22:49:54 +0000152// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
153bool
154EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
155{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000156 EmulateInstruction::Context context;
157 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
158 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000159
160 uint32_t random_data = rand ();
161 const uint32_t addr_byte_size = GetAddressByteSize();
162
Caroline Ticecc96eb52011-02-17 19:20:40 +0000163 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000164 return false;
165
166 return true;
167}
168
Caroline Tice713c2662011-02-11 17:59:55 +0000169// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
170bool
171EmulateInstructionARM::WriteBits32Unknown (int n)
172{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000173 EmulateInstruction::Context context;
174 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
175 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000176
Johnny Chen62ff6f52011-02-11 18:11:22 +0000177 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
179
180 if (!success)
181 return false;
182
183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
184 return false;
185
186 return true;
187}
188
Johnny Chen08c25e82011-01-31 18:02:28 +0000189// Push Multiple Registers stores multiple registers to the stack, storing to
190// consecutive memory locations ending just below the address in SP, and updates
191// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000192bool
Johnny Chen9f687722011-02-18 00:02:28 +0000193EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000194{
195#if 0
196 // ARM pseudo code...
197 if (ConditionPassed())
198 {
199 EncodingSpecificOperations();
200 NullCheckIfThumbEE(13);
201 address = SP - 4*BitCount(registers);
202
203 for (i = 0 to 14)
204 {
205 if (registers<i> == ’1’)
206 {
207 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
208 MemA[address,4] = bits(32) UNKNOWN;
209 else
210 MemA[address,4] = R[i];
211 address = address + 4;
212 }
213 }
214
215 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
216 MemA[address,4] = PCStoreValue();
217
218 SP = SP - 4*BitCount(registers);
219 }
220#endif
221
222 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000224 if (!success)
225 return false;
226
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000228 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000229 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000230 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000231 if (!success)
232 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000234 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000235 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000237 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000238 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000239 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000240 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000241 // if BitCount(registers) < 1 then UNPREDICTABLE;
242 if (BitCount(registers) < 1)
243 return false;
244 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000245 case eEncodingT2:
246 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BitCount(registers) < 2 then UNPREDICTABLE;
249 if (BitCount(registers) < 2)
250 return false;
251 break;
252 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000253 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000257 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000258 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000259 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000261 // Instead of return false, let's handle the following case as well,
262 // which amounts to pushing one reg onto the full descending stacks.
263 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000264 break;
265 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000266 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000267 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000270 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000271 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000272 default:
273 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000274 }
Johnny Chence1ca772011-01-25 01:13:00 +0000275 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000276 addr_t addr = sp - sp_offset;
277 uint32_t i;
278
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000279 EmulateInstruction::Context context;
280 context.type = EmulateInstruction::eContextPushRegisterOnStack;
281 Register dwarf_reg;
282 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000283 Register sp_reg;
284 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000285 for (i=0; i<15; ++i)
286 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000287 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000288 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000289 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000290 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000291 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000292 if (!success)
293 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000294 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 return false;
296 addr += addr_byte_size;
297 }
298 }
299
Johnny Chen7c1bf922011-02-08 23:49:37 +0000300 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000301 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000302 dwarf_reg.num = dwarf_pc;
303 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000305 if (!success)
306 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000307 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310
311 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000312 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000313
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000314 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000315 return false;
316 }
317 return true;
318}
319
Johnny Chenef85e912011-01-31 23:07:40 +0000320// Pop Multiple Registers loads multiple registers from the stack, loading from
321// consecutive memory locations staring at the address in SP, and updates
322// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000323bool
Johnny Chen9f687722011-02-18 00:02:28 +0000324EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000325{
326#if 0
327 // ARM pseudo code...
328 if (ConditionPassed())
329 {
330 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
331 address = SP;
332 for i = 0 to 14
333 if registers<i> == ‘1’ then
334 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
335 if registers<15> == ‘1’ then
336 if UnalignedAllowed then
337 LoadWritePC(MemU[address,4]);
338 else
339 LoadWritePC(MemA[address,4]);
340 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
341 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
342 }
343#endif
344
345 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000350 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000351 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000353 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000354 if (!success)
355 return false;
356 uint32_t registers = 0;
357 uint32_t Rt; // the destination register
358 switch (encoding) {
359 case eEncodingT1:
360 registers = Bits32(opcode, 7, 0);
361 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000362 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000363 registers |= (1u << 15);
364 // if BitCount(registers) < 1 then UNPREDICTABLE;
365 if (BitCount(registers) < 1)
366 return false;
367 break;
368 case eEncodingT2:
369 // Ignore bit 13.
370 registers = Bits32(opcode, 15, 0) & ~0x2000;
371 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000372 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000373 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
375 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
376 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000377 break;
378 case eEncodingT3:
379 Rt = Bits32(opcode, 15, 12);
380 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000381 if (Rt == 13)
382 return false;
383 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000384 return false;
385 registers = (1u << Rt);
386 break;
387 case eEncodingA1:
388 registers = Bits32(opcode, 15, 0);
389 // Instead of return false, let's handle the following case as well,
390 // which amounts to popping one reg from the full descending stacks.
391 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
392
393 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000394 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000395 return false;
396 break;
397 case eEncodingA2:
398 Rt = Bits32(opcode, 15, 12);
399 // if t == 13 then UNPREDICTABLE;
400 if (Rt == dwarf_sp)
401 return false;
402 registers = (1u << Rt);
403 break;
404 default:
405 return false;
406 }
407 addr_t sp_offset = addr_byte_size * BitCount (registers);
408 addr_t addr = sp;
409 uint32_t i, data;
410
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 EmulateInstruction::Context context;
412 context.type = EmulateInstruction::eContextPopRegisterOffStack;
413 Register dwarf_reg;
414 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000415 Register sp_reg;
416 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000417 for (i=0; i<15; ++i)
418 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000419 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000420 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000421 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000422 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000423 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000424 if (!success)
425 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000426 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 return false;
428 addr += addr_byte_size;
429 }
430 }
431
Johnny Chen7c1bf922011-02-08 23:49:37 +0000432 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000434 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000435 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000436 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000437 if (!success)
438 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000439 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000440 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000441 return false;
442 addr += addr_byte_size;
443 }
444
445 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000446 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000447
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000449 return false;
450 }
451 return true;
452}
453
Johnny Chen5b442b72011-01-27 19:34:30 +0000454// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000455// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000456bool
Johnny Chen9f687722011-02-18 00:02:28 +0000457EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000458{
459#if 0
460 // ARM pseudo code...
461 if (ConditionPassed())
462 {
463 EncodingSpecificOperations();
464 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
465 if d == 15 then
466 ALUWritePC(result); // setflags is always FALSE here
467 else
468 R[d] = result;
469 if setflags then
470 APSR.N = result<31>;
471 APSR.Z = IsZeroBit(result);
472 APSR.C = carry;
473 APSR.V = overflow;
474 }
475#endif
476
477 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000478 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000482 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000483 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000484 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000485 if (!success)
486 return false;
487 uint32_t Rd; // the destination register
488 uint32_t imm32;
489 switch (encoding) {
490 case eEncodingT1:
491 Rd = 7;
492 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
493 break;
494 case eEncodingA1:
495 Rd = Bits32(opcode, 15, 12);
496 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
497 break;
498 default:
499 return false;
500 }
501 addr_t sp_offset = imm32;
502 addr_t addr = sp + sp_offset; // a pointer to the stack area
503
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000504 EmulateInstruction::Context context;
505 context.type = EmulateInstruction::eContextRegisterPlusOffset;
506 Register sp_reg;
507 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
508 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000509
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000511 return false;
512 }
513 return true;
514}
515
Johnny Chen2ccad832011-01-28 19:57:25 +0000516// Set r7 or ip to the current stack pointer.
517// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000518bool
Johnny Chen9f687722011-02-18 00:02:28 +0000519EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000520{
521#if 0
522 // ARM pseudo code...
523 if (ConditionPassed())
524 {
525 EncodingSpecificOperations();
526 result = R[m];
527 if d == 15 then
528 ALUWritePC(result); // setflags is always FALSE here
529 else
530 R[d] = result;
531 if setflags then
532 APSR.N = result<31>;
533 APSR.Z = IsZeroBit(result);
534 // APSR.C unchanged
535 // APSR.V unchanged
536 }
537#endif
538
539 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 //if (!success)
542 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000543
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000544 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000545 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000546 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000547 if (!success)
548 return false;
549 uint32_t Rd; // the destination register
550 switch (encoding) {
551 case eEncodingT1:
552 Rd = 7;
553 break;
554 case eEncodingA1:
555 Rd = 12;
556 break;
557 default:
558 return false;
559 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000560
561 EmulateInstruction::Context context;
562 context.type = EmulateInstruction::eContextRegisterPlusOffset;
563 Register sp_reg;
564 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
565 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000566
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000568 return false;
569 }
570 return true;
571}
572
Johnny Chen1c13b622011-01-29 00:11:15 +0000573// Move from high register (r8-r15) to low register (r0-r7).
574// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000575bool
Johnny Chen9f687722011-02-18 00:02:28 +0000576EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000577{
Johnny Chen9f687722011-02-18 00:02:28 +0000578 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000579}
580
581// Move from register to register.
582// MOV (register)
583bool
Johnny Chen9f687722011-02-18 00:02:28 +0000584EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000585{
Johnny Chen1c13b622011-01-29 00:11:15 +0000586#if 0
587 // ARM pseudo code...
588 if (ConditionPassed())
589 {
590 EncodingSpecificOperations();
591 result = R[m];
592 if d == 15 then
593 ALUWritePC(result); // setflags is always FALSE here
594 else
595 R[d] = result;
596 if setflags then
597 APSR.N = result<31>;
598 APSR.Z = IsZeroBit(result);
599 // APSR.C unchanged
600 // APSR.V unchanged
601 }
602#endif
603
604 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000605 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 if (!success)
607 return false;
608
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000609 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000610 {
611 uint32_t Rm; // the source register
612 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000613 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 switch (encoding) {
615 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000616 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000617 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000619 if (Rd == 15 && InITBlock() && !LastInITBlock())
620 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000621 break;
622 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000624 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000625 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000626 if (InITBlock())
627 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000628 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000629 case eEncodingT3:
630 Rd = Bits32(opcode, 11, 8);
631 Rm = Bits32(opcode, 3, 0);
632 setflags = BitIsSet(opcode, 20);
633 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
634 if (setflags && (BadReg(Rd) || BadReg(Rm)))
635 return false;
636 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
637 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
638 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000639 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000640 case eEncodingA1:
641 Rd = Bits32(opcode, 15, 12);
642 Rm = Bits32(opcode, 3, 0);
643 setflags = BitIsSet(opcode, 20);
644 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
645 // TODO: Emulate SUBS PC, LR and related instructions.
646 if (Rd == 15 && setflags)
647 return false;
648 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 default:
650 return false;
651 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000652 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000653 if (!success)
654 return false;
655
656 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000657 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000658 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000659 Register dwarf_reg;
660 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000661 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000662
Johnny Chen10530c22011-02-17 22:37:12 +0000663 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000664 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000665 }
666 return true;
667}
668
Johnny Chen357c30f2011-02-14 22:04:25 +0000669// Move (immediate) writes an immediate value to the destination register. It
670// can optionally update the condition flags based on the value.
671// MOV (immediate)
672bool
Johnny Chen9f687722011-02-18 00:02:28 +0000673EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000674{
675#if 0
676 // ARM pseudo code...
677 if (ConditionPassed())
678 {
679 EncodingSpecificOperations();
680 result = imm32;
681 if d == 15 then // Can only occur for ARM encoding
682 ALUWritePC(result); // setflags is always FALSE here
683 else
684 R[d] = result;
685 if setflags then
686 APSR.N = result<31>;
687 APSR.Z = IsZeroBit(result);
688 APSR.C = carry;
689 // APSR.V unchanged
690 }
691#endif
692 bool success = false;
693 const uint32_t opcode = OpcodeAsUnsigned (&success);
694 if (!success)
695 return false;
696
697 if (ConditionPassed())
698 {
699 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000700 uint32_t imm32; // the immediate value to be written to Rd
701 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
702 bool setflags;
703 switch (encoding) {
704 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000705 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000706 setflags = !InITBlock();
707 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000708 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000709 break;
710 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000711 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000712 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000713 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000714 if (BadReg(Rd))
715 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000716 break;
717 default:
718 return false;
719 }
720 uint32_t result = imm32;
721
722 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000723 EmulateInstruction::Context context;
724 context.type = EmulateInstruction::eContextImmediate;
725 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000726
Johnny Chen10530c22011-02-17 22:37:12 +0000727 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000728 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000729 }
730 return true;
731}
732
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000733// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
734// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
735// unsigned values.
736//
737// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
738// limited to only a few forms of the instruction.
739bool
740EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
741{
742#if 0
743 if ConditionPassed() then
744 EncodingSpecificOperations();
745 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
746 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
747 result = operand1 * operand2;
748 R[d] = result<31:0>;
749 if setflags then
750 APSR.N = result<31>;
751 APSR.Z = IsZeroBit(result);
752 if ArchVersion() == 4 then
753 APSR.C = bit UNKNOWN;
754 // else APSR.C unchanged
755 // APSR.V always unchanged
756#endif
757
758 bool success = false;
759 const uint32_t opcode = OpcodeAsUnsigned (&success);
760 if (!success)
761 return false;
762
763 if (ConditionPassed())
764 {
765 uint32_t d;
766 uint32_t n;
767 uint32_t m;
768 bool setflags;
769
770 // EncodingSpecificOperations();
771 switch (encoding)
772 {
773 case eEncodingT1:
774 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
775 d = Bits32 (opcode, 2, 0);
776 n = Bits32 (opcode, 5, 3);
777 m = Bits32 (opcode, 2, 0);
778 setflags = !InITBlock();
779
780 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
781 if ((ArchVersion() < ARMv6) && (d == n))
782 return false;
783
784 break;
785
786 case eEncodingT2:
787 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
788 d = Bits32 (opcode, 11, 8);
789 n = Bits32 (opcode, 19, 16);
790 m = Bits32 (opcode, 3, 0);
791 setflags = false;
792
793 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
794 if (BadReg (d) || BadReg (n) || BadReg (m))
795 return false;
796
797 break;
798
799 case eEncodingA1:
800 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
801 d = Bits32 (opcode, 19, 16);
802 n = Bits32 (opcode, 3, 0);
803 m = Bits32 (opcode, 11, 8);
804 setflags = BitIsSet (opcode, 20);
805
806 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
807 if ((d == 15) || (n == 15) || (m == 15))
808 return false;
809
810 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
811 if ((ArchVersion() < ARMv6) && (d == n))
812 return false;
813
814 break;
815
816 default:
817 return false;
818 }
819
820 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
821 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
822 if (!success)
823 return false;
824
825 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
826 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
827 if (!success)
828 return false;
829
830 // result = operand1 * operand2;
831 uint64_t result = operand1 * operand2;
832
833 // R[d] = result<31:0>;
834 Register op1_reg;
835 Register op2_reg;
836 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
837 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
838
839 EmulateInstruction::Context context;
840 context.type = eContextMultiplication;
841 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
842
843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
844 return false;
845
846 // if setflags then
847 if (setflags)
848 {
849 // APSR.N = result<31>;
850 // APSR.Z = IsZeroBit(result);
851 m_new_inst_cpsr = m_inst_cpsr;
852 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
853 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
854 if (m_new_inst_cpsr != m_inst_cpsr)
855 {
856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
857 return false;
858 }
859
860 // if ArchVersion() == 4 then
861 // APSR.C = bit UNKNOWN;
862 }
863 }
864 return true;
865}
866
Johnny Chend642a6a2011-02-22 01:01:03 +0000867// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
868// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000869bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000870EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000871{
872#if 0
873 // ARM pseudo code...
874 if (ConditionPassed())
875 {
876 EncodingSpecificOperations();
877 result = NOT(imm32);
878 if d == 15 then // Can only occur for ARM encoding
879 ALUWritePC(result); // setflags is always FALSE here
880 else
881 R[d] = result;
882 if setflags then
883 APSR.N = result<31>;
884 APSR.Z = IsZeroBit(result);
885 APSR.C = carry;
886 // APSR.V unchanged
887 }
888#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000889 bool success = false;
890 const uint32_t opcode = OpcodeAsUnsigned (&success);
891 if (!success)
892 return false;
893
894 if (ConditionPassed())
895 {
896 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000897 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
898 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000899 bool setflags;
900 switch (encoding) {
901 case eEncodingT1:
902 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000904 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000905 break;
906 case eEncodingA1:
907 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000908 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000909 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
911 // TODO: Emulate SUBS PC, LR and related instructions.
912 if (Rd == 15 && setflags)
913 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000914 break;
915 default:
916 return false;
917 }
918 uint32_t result = ~imm32;
919
920 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000921 EmulateInstruction::Context context;
922 context.type = EmulateInstruction::eContextImmediate;
923 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000924
Johnny Chen10530c22011-02-17 22:37:12 +0000925 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000926 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000927 }
928 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000929}
930
Johnny Chend642a6a2011-02-22 01:01:03 +0000931// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
932// It can optionally update the condition flags based on the result.
933bool
934EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
935{
936#if 0
937 // ARM pseudo code...
938 if (ConditionPassed())
939 {
940 EncodingSpecificOperations();
941 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
942 result = NOT(shifted);
943 if d == 15 then // Can only occur for ARM encoding
944 ALUWritePC(result); // setflags is always FALSE here
945 else
946 R[d] = result;
947 if setflags then
948 APSR.N = result<31>;
949 APSR.Z = IsZeroBit(result);
950 APSR.C = carry;
951 // APSR.V unchanged
952 }
953#endif
954
955 bool success = false;
956 const uint32_t opcode = OpcodeAsUnsigned (&success);
957 if (!success)
958 return false;
959
960 if (ConditionPassed())
961 {
962 uint32_t Rm; // the source register
963 uint32_t Rd; // the destination register
964 ARM_ShifterType shift_t;
965 uint32_t shift_n; // the shift applied to the value read from Rm
966 bool setflags;
967 uint32_t carry; // the carry bit after the shift operation
968 switch (encoding) {
969 case eEncodingT1:
970 Rd = Bits32(opcode, 2, 0);
971 Rm = Bits32(opcode, 5, 3);
972 setflags = !InITBlock();
973 shift_t = SRType_LSL;
974 shift_n = 0;
975 if (InITBlock())
976 return false;
977 break;
978 case eEncodingT2:
979 Rd = Bits32(opcode, 11, 8);
980 Rm = Bits32(opcode, 3, 0);
981 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000982 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000984 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000985 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000986 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000987 case eEncodingA1:
988 Rd = Bits32(opcode, 15, 12);
989 Rm = Bits32(opcode, 3, 0);
990 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000991 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000992 break;
993 default:
994 return false;
995 }
996 uint32_t value = ReadCoreReg(Rm, &success);
997 if (!success)
998 return false;
999
1000 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1001 uint32_t result = ~shifted;
1002
1003 // The context specifies that an immediate is to be moved into Rd.
1004 EmulateInstruction::Context context;
1005 context.type = EmulateInstruction::eContextImmediate;
1006 context.SetNoArgs ();
1007
1008 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1009 return false;
1010 }
1011 return true;
1012}
1013
Johnny Chen788e0552011-01-27 22:52:23 +00001014// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1015// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001016bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001017EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001018{
1019#if 0
1020 // ARM pseudo code...
1021 if (ConditionPassed())
1022 {
1023 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1024 base = Align(PC,4);
1025 address = if add then (base + imm32) else (base - imm32);
1026 data = MemU[address,4];
1027 if t == 15 then
1028 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1029 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1030 R[t] = data;
1031 else // Can only apply before ARMv7
1032 if CurrentInstrSet() == InstrSet_ARM then
1033 R[t] = ROR(data, 8*UInt(address<1:0>));
1034 else
1035 R[t] = bits(32) UNKNOWN;
1036 }
1037#endif
1038
1039 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001040 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001041 if (!success)
1042 return false;
1043
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001044 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001045 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001046 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001047 if (!success)
1048 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001049
1050 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001051 EmulateInstruction::Context context;
1052 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1053 Register pc_reg;
1054 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1055 context.SetRegisterPlusOffset (pc_reg, 0);
1056
Johnny Chenc9de9102011-02-11 19:12:30 +00001057 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001058 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001059 bool add; // +imm32 or -imm32?
1060 addr_t base; // the base address
1061 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001062 uint32_t data; // the literal data value from the PC relative load
1063 switch (encoding) {
1064 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001065 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001066 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001067 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001068 break;
1069 case eEncodingT2:
1070 Rt = Bits32(opcode, 15, 12);
1071 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1072 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001073 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001074 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001075 break;
1076 default:
1077 return false;
1078 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001079
Johnny Chene39f22d2011-02-19 01:36:13 +00001080 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001081 if (add)
1082 address = base + imm32;
1083 else
1084 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001085
1086 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001087 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001088 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001089 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001090
1091 if (Rt == 15)
1092 {
1093 if (Bits32(address, 1, 0) == 0)
1094 {
1095 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001096 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001097 return false;
1098 }
1099 else
1100 return false;
1101 }
1102 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1103 {
1104 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1105 return false;
1106 }
1107 else // We don't handle ARM for now.
1108 return false;
1109
Johnny Chen788e0552011-01-27 22:52:23 +00001110 }
1111 return true;
1112}
1113
Johnny Chen5b442b72011-01-27 19:34:30 +00001114// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001115// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001116bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001117EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001118{
1119#if 0
1120 // ARM pseudo code...
1121 if (ConditionPassed())
1122 {
1123 EncodingSpecificOperations();
1124 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1125 if d == 15 then // Can only occur for ARM encoding
1126 ALUWritePC(result); // setflags is always FALSE here
1127 else
1128 R[d] = result;
1129 if setflags then
1130 APSR.N = result<31>;
1131 APSR.Z = IsZeroBit(result);
1132 APSR.C = carry;
1133 APSR.V = overflow;
1134 }
1135#endif
1136
1137 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001139 if (!success)
1140 return false;
1141
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001142 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001143 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001144 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001145 if (!success)
1146 return false;
1147 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001148 uint32_t d;
1149 bool setflags;
1150 switch (encoding)
1151 {
1152 case eEncodingT1:
1153 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:’00’, 32);
1154 d = Bits32 (opcode, 10, 8);
1155 setflags = false;
1156 imm32 = (Bits32 (opcode, 7, 0) << 2);
1157
1158 break;
1159
1160 case eEncodingT2:
1161 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:’00’, 32);
1162 d = 13;
1163 setflags = false;
1164 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1165
1166 break;
1167
1168 default:
1169 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001170 }
1171 addr_t sp_offset = imm32;
1172 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1173
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001174 EmulateInstruction::Context context;
1175 context.type = EmulateInstruction::eContextAdjustStackPointer;
1176 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001177
Caroline Ticee2212882011-03-22 22:38:28 +00001178 if (d == 15)
1179 {
1180 if (!ALUWritePC (context, addr))
1181 return false;
1182 }
1183 else
1184 {
1185 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1186 return false;
1187 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001188 }
1189 return true;
1190}
1191
1192// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001193// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001194bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001195EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001196{
1197#if 0
1198 // ARM pseudo code...
1199 if (ConditionPassed())
1200 {
1201 EncodingSpecificOperations();
1202 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1203 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1204 if d == 15 then
1205 ALUWritePC(result); // setflags is always FALSE here
1206 else
1207 R[d] = result;
1208 if setflags then
1209 APSR.N = result<31>;
1210 APSR.Z = IsZeroBit(result);
1211 APSR.C = carry;
1212 APSR.V = overflow;
1213 }
1214#endif
1215
1216 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001218 if (!success)
1219 return false;
1220
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001221 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001222 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001223 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001224 if (!success)
1225 return false;
1226 uint32_t Rm; // the second operand
1227 switch (encoding) {
1228 case eEncodingT2:
1229 Rm = Bits32(opcode, 6, 3);
1230 break;
1231 default:
1232 return false;
1233 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001234 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001235 if (!success)
1236 return false;
1237
1238 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1239
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001240 EmulateInstruction::Context context;
1241 context.type = EmulateInstruction::eContextAdjustStackPointer;
1242 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001243
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001244 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001245 return false;
1246 }
1247 return true;
1248}
1249
Johnny Chen9b8d7832011-02-02 01:13:56 +00001250// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1251// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1252// from Thumb to ARM.
1253// BLX (immediate)
1254bool
1255EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1256{
1257#if 0
1258 // ARM pseudo code...
1259 if (ConditionPassed())
1260 {
1261 EncodingSpecificOperations();
1262 if CurrentInstrSet() == InstrSet_ARM then
1263 LR = PC - 4;
1264 else
1265 LR = PC<31:1> : '1';
1266 if targetInstrSet == InstrSet_ARM then
1267 targetAddress = Align(PC,4) + imm32;
1268 else
1269 targetAddress = PC + imm32;
1270 SelectInstrSet(targetInstrSet);
1271 BranchWritePC(targetAddress);
1272 }
1273#endif
1274
1275 bool success = false;
1276 const uint32_t opcode = OpcodeAsUnsigned (&success);
1277 if (!success)
1278 return false;
1279
1280 if (ConditionPassed())
1281 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001282 EmulateInstruction::Context context;
1283 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001284 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001285 if (!success)
1286 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001287 addr_t lr; // next instruction address
1288 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 int32_t imm32; // PC-relative offset
1290 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001291 case eEncodingT1:
1292 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001293 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001294 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001295 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001296 uint32_t J1 = Bit32(opcode, 13);
1297 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001298 uint32_t imm11 = Bits32(opcode, 10, 0);
1299 uint32_t I1 = !(J1 ^ S);
1300 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001301 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001302 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001303 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001305 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001306 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001307 break;
1308 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001309 case eEncodingT2:
1310 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001311 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001312 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001313 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001314 uint32_t J1 = Bit32(opcode, 13);
1315 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001316 uint32_t imm10L = Bits32(opcode, 10, 1);
1317 uint32_t I1 = !(J1 ^ S);
1318 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001319 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001320 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001321 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001322 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001323 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001324 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001325 break;
1326 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001327 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001328 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001329 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001330 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001331 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001332 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001333 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001334 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001335 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001336 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001337 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001338 break;
1339 default:
1340 return false;
1341 }
1342 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1343 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001344 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001345 return false;
1346 }
1347 return true;
1348}
1349
1350// Branch with Link and Exchange (register) calls a subroutine at an address and
1351// instruction set specified by a register.
1352// BLX (register)
1353bool
1354EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1355{
1356#if 0
1357 // ARM pseudo code...
1358 if (ConditionPassed())
1359 {
1360 EncodingSpecificOperations();
1361 target = R[m];
1362 if CurrentInstrSet() == InstrSet_ARM then
1363 next_instr_addr = PC - 4;
1364 LR = next_instr_addr;
1365 else
1366 next_instr_addr = PC - 2;
1367 LR = next_instr_addr<31:1> : ‘1’;
1368 BXWritePC(target);
1369 }
1370#endif
1371
1372 bool success = false;
1373 const uint32_t opcode = OpcodeAsUnsigned (&success);
1374 if (!success)
1375 return false;
1376
1377 if (ConditionPassed())
1378 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001379 EmulateInstruction::Context context;
1380 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001381 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001382 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001383 if (!success)
1384 return false;
1385 uint32_t Rm; // the register with the target address
1386 switch (encoding) {
1387 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001388 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001389 Rm = Bits32(opcode, 6, 3);
1390 // if m == 15 then UNPREDICTABLE;
1391 if (Rm == 15)
1392 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001393 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001394 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001395 break;
1396 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001397 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001398 Rm = Bits32(opcode, 3, 0);
1399 // if m == 15 then UNPREDICTABLE;
1400 if (Rm == 15)
1401 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001402 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001403 default:
1404 return false;
1405 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001406 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001407 if (!success)
1408 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001409 Register dwarf_reg;
1410 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1411 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001412 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1413 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001414 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001415 return false;
1416 }
1417 return true;
1418}
1419
Johnny Chenab3b3512011-02-12 00:10:51 +00001420// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001421bool
1422EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1423{
1424#if 0
1425 // ARM pseudo code...
1426 if (ConditionPassed())
1427 {
1428 EncodingSpecificOperations();
1429 BXWritePC(R[m]);
1430 }
1431#endif
1432
1433 bool success = false;
1434 const uint32_t opcode = OpcodeAsUnsigned (&success);
1435 if (!success)
1436 return false;
1437
1438 if (ConditionPassed())
1439 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001440 EmulateInstruction::Context context;
1441 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001442 uint32_t Rm; // the register with the target address
1443 switch (encoding) {
1444 case eEncodingT1:
1445 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001446 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001447 return false;
1448 break;
1449 case eEncodingA1:
1450 Rm = Bits32(opcode, 3, 0);
1451 break;
1452 default:
1453 return false;
1454 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001455 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001456 if (!success)
1457 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001458
1459 Register dwarf_reg;
1460 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001461 context.SetRegister (dwarf_reg);
1462 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001463 return false;
1464 }
1465 return true;
1466}
1467
Johnny Chen59e6ab72011-02-24 21:01:20 +00001468// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1469// address and instruction set specified by a register as though it were a BX instruction.
1470//
1471// TODO: Emulate Jazelle architecture?
1472// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1473bool
1474EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1475{
1476#if 0
1477 // ARM pseudo code...
1478 if (ConditionPassed())
1479 {
1480 EncodingSpecificOperations();
1481 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1482 BXWritePC(R[m]);
1483 else
1484 if JazelleAcceptsExecution() then
1485 SwitchToJazelleExecution();
1486 else
1487 SUBARCHITECTURE_DEFINED handler call;
1488 }
1489#endif
1490
1491 bool success = false;
1492 const uint32_t opcode = OpcodeAsUnsigned (&success);
1493 if (!success)
1494 return false;
1495
1496 if (ConditionPassed())
1497 {
1498 EmulateInstruction::Context context;
1499 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1500 uint32_t Rm; // the register with the target address
1501 switch (encoding) {
1502 case eEncodingT1:
1503 Rm = Bits32(opcode, 19, 16);
1504 if (BadReg(Rm))
1505 return false;
1506 if (InITBlock() && !LastInITBlock())
1507 return false;
1508 break;
1509 case eEncodingA1:
1510 Rm = Bits32(opcode, 3, 0);
1511 if (Rm == 15)
1512 return false;
1513 break;
1514 default:
1515 return false;
1516 }
1517 addr_t target = ReadCoreReg (Rm, &success);
1518 if (!success)
1519 return false;
1520
1521 Register dwarf_reg;
1522 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1523 context.SetRegister (dwarf_reg);
1524 if (!BXWritePC(context, target))
1525 return false;
1526 }
1527 return true;
1528}
1529
Johnny Chen0d0148e2011-01-28 02:26:08 +00001530// Set r7 to point to some ip offset.
1531// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001533EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001534{
1535#if 0
1536 // ARM pseudo code...
1537 if (ConditionPassed())
1538 {
1539 EncodingSpecificOperations();
1540 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1541 if d == 15 then // Can only occur for ARM encoding
1542 ALUWritePC(result); // setflags is always FALSE here
1543 else
1544 R[d] = result;
1545 if setflags then
1546 APSR.N = result<31>;
1547 APSR.Z = IsZeroBit(result);
1548 APSR.C = carry;
1549 APSR.V = overflow;
1550 }
1551#endif
1552
1553 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001554 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001555 if (!success)
1556 return false;
1557
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001558 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001559 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001560 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001561 if (!success)
1562 return false;
1563 uint32_t imm32;
1564 switch (encoding) {
1565 case eEncodingA1:
1566 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1567 break;
1568 default:
1569 return false;
1570 }
1571 addr_t ip_offset = imm32;
1572 addr_t addr = ip - ip_offset; // the adjusted ip value
1573
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001574 EmulateInstruction::Context context;
1575 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1576 Register dwarf_reg;
1577 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1578 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001579
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001580 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001581 return false;
1582 }
1583 return true;
1584}
1585
1586// Set ip to point to some stack offset.
1587// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001589EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001590{
1591#if 0
1592 // ARM pseudo code...
1593 if (ConditionPassed())
1594 {
1595 EncodingSpecificOperations();
1596 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1597 if d == 15 then // Can only occur for ARM encoding
1598 ALUWritePC(result); // setflags is always FALSE here
1599 else
1600 R[d] = result;
1601 if setflags then
1602 APSR.N = result<31>;
1603 APSR.Z = IsZeroBit(result);
1604 APSR.C = carry;
1605 APSR.V = overflow;
1606 }
1607#endif
1608
1609 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001610 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001611 if (!success)
1612 return false;
1613
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001614 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001615 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001616 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001617 if (!success)
1618 return false;
1619 uint32_t imm32;
1620 switch (encoding) {
1621 case eEncodingA1:
1622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1623 break;
1624 default:
1625 return false;
1626 }
1627 addr_t sp_offset = imm32;
1628 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1629
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001630 EmulateInstruction::Context context;
1631 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1632 Register dwarf_reg;
1633 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1634 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001635
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001637 return false;
1638 }
1639 return true;
1640}
1641
Johnny Chenc9e747f2011-02-23 01:55:07 +00001642// This instruction subtracts an immediate value from the SP value, and writes
1643// the result to the destination register.
1644//
1645// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001646bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001647EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001648{
1649#if 0
1650 // ARM pseudo code...
1651 if (ConditionPassed())
1652 {
1653 EncodingSpecificOperations();
1654 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001655 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001656 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001657 else
1658 R[d] = result;
1659 if setflags then
1660 APSR.N = result<31>;
1661 APSR.Z = IsZeroBit(result);
1662 APSR.C = carry;
1663 APSR.V = overflow;
1664 }
1665#endif
1666
1667 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001668 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001669 if (!success)
1670 return false;
1671
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001672 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001673 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001674 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001675 if (!success)
1676 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001677
1678 uint32_t Rd;
1679 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001680 uint32_t imm32;
1681 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001682 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001683 Rd = 13;
1684 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001685 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001686 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001687 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001688 Rd = Bits32(opcode, 11, 8);
1689 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001690 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001691 if (Rd == 15 && setflags)
1692 return EmulateCMPImm(eEncodingT2);
1693 if (Rd == 15 && !setflags)
1694 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001695 break;
1696 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001697 Rd = Bits32(opcode, 11, 8);
1698 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001699 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001700 if (Rd == 15)
1701 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001702 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001703 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001704 Rd = Bits32(opcode, 15, 12);
1705 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001706 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001707 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1708 // TODO: Emulate SUBS PC, LR and related instructions.
1709 if (Rd == 15 && setflags)
1710 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001711 break;
1712 default:
1713 return false;
1714 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001715 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1716
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001717 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001718 if (Rd == 13)
1719 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001720 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1721 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001722 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001723 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001724 }
1725 else
1726 {
1727 context.type = EmulateInstruction::eContextImmediate;
1728 context.SetNoArgs ();
1729 }
1730
1731 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001732 return false;
1733 }
1734 return true;
1735}
1736
Johnny Chen08c25e82011-01-31 18:02:28 +00001737// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001738bool
1739EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001740{
1741#if 0
1742 // ARM pseudo code...
1743 if (ConditionPassed())
1744 {
1745 EncodingSpecificOperations();
1746 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1747 address = if index then offset_addr else R[n];
1748 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1749 if wback then R[n] = offset_addr;
1750 }
1751#endif
1752
1753 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001754 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001755 if (!success)
1756 return false;
1757
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001758 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001759 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001760 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001761 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001762 if (!success)
1763 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001764 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001765 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001766 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1767
1768 bool index;
1769 bool add;
1770 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001771 switch (encoding) {
1772 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001773 Rt = Bits32(opcode, 15, 12);
1774 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001775 Rn = Bits32 (opcode, 19, 16);
1776
1777 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1778 return false;
1779
1780 index = BitIsSet (opcode, 24);
1781 add = BitIsSet (opcode, 23);
1782 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1783
1784 if (wback && ((Rn == 15) || (Rn == Rt)))
1785 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001786 break;
1787 default:
1788 return false;
1789 }
Caroline Tice3e407972011-03-18 19:41:00 +00001790 addr_t offset_addr;
1791 if (add)
1792 offset_addr = sp + imm12;
1793 else
1794 offset_addr = sp - imm12;
1795
1796 addr_t addr;
1797 if (index)
1798 addr = offset_addr;
1799 else
1800 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001801
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001802 EmulateInstruction::Context context;
1803 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001804 Register sp_reg;
1805 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1806 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001807 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001808 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001809 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001810 if (!success)
1811 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001812 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001813 return false;
1814 }
1815 else
1816 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001817 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001818 if (!success)
1819 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001820 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001821 return false;
1822 }
1823
Caroline Tice3e407972011-03-18 19:41:00 +00001824
1825 if (wback)
1826 {
1827 context.type = EmulateInstruction::eContextAdjustStackPointer;
1828 context.SetImmediateSigned (addr - sp);
1829 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1830 return false;
1831 }
Johnny Chence1ca772011-01-25 01:13:00 +00001832 }
1833 return true;
1834}
1835
Johnny Chen08c25e82011-01-31 18:02:28 +00001836// Vector Push stores multiple extension registers to the stack.
1837// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001838bool
1839EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001840{
1841#if 0
1842 // ARM pseudo code...
1843 if (ConditionPassed())
1844 {
1845 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1846 address = SP - imm32;
1847 SP = SP - imm32;
1848 if single_regs then
1849 for r = 0 to regs-1
1850 MemA[address,4] = S[d+r]; address = address+4;
1851 else
1852 for r = 0 to regs-1
1853 // Store as two word-aligned words in the correct order for current endianness.
1854 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1855 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1856 address = address+8;
1857 }
1858#endif
1859
1860 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001861 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001862 if (!success)
1863 return false;
1864
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001865 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001866 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001867 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001868 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001869 if (!success)
1870 return false;
1871 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001872 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001873 uint32_t imm32; // stack offset
1874 uint32_t regs; // number of registers
1875 switch (encoding) {
1876 case eEncodingT1:
1877 case eEncodingA1:
1878 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001879 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001880 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1881 // If UInt(imm8) is odd, see "FSTMX".
1882 regs = Bits32(opcode, 7, 0) / 2;
1883 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1884 if (regs == 0 || regs > 16 || (d + regs) > 32)
1885 return false;
1886 break;
1887 case eEncodingT2:
1888 case eEncodingA2:
1889 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001890 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001891 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1892 regs = Bits32(opcode, 7, 0);
1893 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1894 if (regs == 0 || regs > 16 || (d + regs) > 32)
1895 return false;
1896 break;
1897 default:
1898 return false;
1899 }
1900 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1901 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1902 addr_t sp_offset = imm32;
1903 addr_t addr = sp - sp_offset;
1904 uint32_t i;
1905
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001906 EmulateInstruction::Context context;
1907 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1908 Register dwarf_reg;
1909 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001910 for (i=d; i<regs; ++i)
1911 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001912 dwarf_reg.num = start_reg + i;
1913 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001914 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001915 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001916 if (!success)
1917 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001918 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001919 return false;
1920 addr += reg_byte_size;
1921 }
1922
1923 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001924 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001925
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001926 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001927 return false;
1928 }
1929 return true;
1930}
1931
Johnny Chen587a0a42011-02-01 18:35:28 +00001932// Vector Pop loads multiple extension registers from the stack.
1933// It also updates SP to point just above the loaded data.
1934bool
1935EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1936{
1937#if 0
1938 // ARM pseudo code...
1939 if (ConditionPassed())
1940 {
1941 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1942 address = SP;
1943 SP = SP + imm32;
1944 if single_regs then
1945 for r = 0 to regs-1
1946 S[d+r] = MemA[address,4]; address = address+4;
1947 else
1948 for r = 0 to regs-1
1949 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1950 // Combine the word-aligned words in the correct order for current endianness.
1951 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1952 }
1953#endif
1954
1955 bool success = false;
1956 const uint32_t opcode = OpcodeAsUnsigned (&success);
1957 if (!success)
1958 return false;
1959
1960 if (ConditionPassed())
1961 {
1962 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001963 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001964 if (!success)
1965 return false;
1966 bool single_regs;
1967 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1968 uint32_t imm32; // stack offset
1969 uint32_t regs; // number of registers
1970 switch (encoding) {
1971 case eEncodingT1:
1972 case eEncodingA1:
1973 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001974 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001975 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1976 // If UInt(imm8) is odd, see "FLDMX".
1977 regs = Bits32(opcode, 7, 0) / 2;
1978 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1979 if (regs == 0 || regs > 16 || (d + regs) > 32)
1980 return false;
1981 break;
1982 case eEncodingT2:
1983 case eEncodingA2:
1984 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001985 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001986 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1987 regs = Bits32(opcode, 7, 0);
1988 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1989 if (regs == 0 || regs > 16 || (d + regs) > 32)
1990 return false;
1991 break;
1992 default:
1993 return false;
1994 }
1995 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1996 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1997 addr_t sp_offset = imm32;
1998 addr_t addr = sp;
1999 uint32_t i;
2000 uint64_t data; // uint64_t to accomodate 64-bit registers.
2001
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002002 EmulateInstruction::Context context;
2003 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2004 Register dwarf_reg;
2005 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00002006 for (i=d; i<regs; ++i)
2007 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002008 dwarf_reg.num = start_reg + i;
2009 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002010 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002011 if (!success)
2012 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002013 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002014 return false;
2015 addr += reg_byte_size;
2016 }
2017
2018 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002019 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002020
2021 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2022 return false;
2023 }
2024 return true;
2025}
2026
Johnny Chenb77be412011-02-04 00:40:18 +00002027// SVC (previously SWI)
2028bool
2029EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
2030{
2031#if 0
2032 // ARM pseudo code...
2033 if (ConditionPassed())
2034 {
2035 EncodingSpecificOperations();
2036 CallSupervisor();
2037 }
2038#endif
2039
2040 bool success = false;
2041 const uint32_t opcode = OpcodeAsUnsigned (&success);
2042 if (!success)
2043 return false;
2044
2045 if (ConditionPassed())
2046 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002047 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002048 addr_t lr; // next instruction address
2049 if (!success)
2050 return false;
2051 uint32_t imm32; // the immediate constant
2052 uint32_t mode; // ARM or Thumb mode
2053 switch (encoding) {
2054 case eEncodingT1:
2055 lr = (pc + 2) | 1u; // return address
2056 imm32 = Bits32(opcode, 7, 0);
2057 mode = eModeThumb;
2058 break;
2059 case eEncodingA1:
2060 lr = pc + 4; // return address
2061 imm32 = Bits32(opcode, 23, 0);
2062 mode = eModeARM;
2063 break;
2064 default:
2065 return false;
2066 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002067
2068 EmulateInstruction::Context context;
2069 context.type = EmulateInstruction::eContextSupervisorCall;
2070 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002071 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2072 return false;
2073 }
2074 return true;
2075}
2076
Johnny Chenc315f862011-02-05 00:46:10 +00002077// If Then makes up to four following instructions (the IT block) conditional.
2078bool
2079EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2080{
2081#if 0
2082 // ARM pseudo code...
2083 EncodingSpecificOperations();
2084 ITSTATE.IT<7:0> = firstcond:mask;
2085#endif
2086
2087 bool success = false;
2088 const uint32_t opcode = OpcodeAsUnsigned (&success);
2089 if (!success)
2090 return false;
2091
2092 m_it_session.InitIT(Bits32(opcode, 7, 0));
2093 return true;
2094}
2095
Johnny Chen3b620b32011-02-07 20:11:47 +00002096// Branch causes a branch to a target address.
2097bool
2098EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2099{
2100#if 0
2101 // ARM pseudo code...
2102 if (ConditionPassed())
2103 {
2104 EncodingSpecificOperations();
2105 BranchWritePC(PC + imm32);
2106 }
2107#endif
2108
2109 bool success = false;
2110 const uint32_t opcode = OpcodeAsUnsigned (&success);
2111 if (!success)
2112 return false;
2113
Johnny Chen9ee056b2011-02-08 00:06:35 +00002114 if (ConditionPassed())
2115 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002116 EmulateInstruction::Context context;
2117 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002118 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002119 if (!success)
2120 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002121 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002122 int32_t imm32; // PC-relative offset
2123 switch (encoding) {
2124 case eEncodingT1:
2125 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2126 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002127 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002128 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002129 break;
2130 case eEncodingT2:
2131 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002132 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002133 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002134 break;
2135 case eEncodingT3:
2136 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2137 {
Johnny Chenbd599902011-02-10 21:39:01 +00002138 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002139 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002140 uint32_t J1 = Bit32(opcode, 13);
2141 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002142 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002143 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002144 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002145 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002146 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002147 break;
2148 }
2149 case eEncodingT4:
2150 {
Johnny Chenbd599902011-02-10 21:39:01 +00002151 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002152 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002153 uint32_t J1 = Bit32(opcode, 13);
2154 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002155 uint32_t imm11 = Bits32(opcode, 10, 0);
2156 uint32_t I1 = !(J1 ^ S);
2157 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002158 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002159 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002160 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002161 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002162 break;
2163 }
2164 case eEncodingA1:
2165 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002166 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002167 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002168 break;
2169 default:
2170 return false;
2171 }
2172 if (!BranchWritePC(context, target))
2173 return false;
2174 }
2175 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002176}
2177
Johnny Chen53ebab72011-02-08 23:21:57 +00002178// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2179// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2180// CBNZ, CBZ
2181bool
2182EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2183{
2184#if 0
2185 // ARM pseudo code...
2186 EncodingSpecificOperations();
2187 if nonzero ^ IsZero(R[n]) then
2188 BranchWritePC(PC + imm32);
2189#endif
2190
2191 bool success = false;
2192 const uint32_t opcode = OpcodeAsUnsigned (&success);
2193 if (!success)
2194 return false;
2195
2196 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002197 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002198 if (!success)
2199 return false;
2200
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002201 EmulateInstruction::Context context;
2202 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002203 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002204 if (!success)
2205 return false;
2206
2207 addr_t target; // target address
2208 uint32_t imm32; // PC-relative offset to branch forward
2209 bool nonzero;
2210 switch (encoding) {
2211 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002212 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002213 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002214 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002215 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002216 break;
2217 default:
2218 return false;
2219 }
2220 if (nonzero ^ (reg_val == 0))
2221 if (!BranchWritePC(context, target))
2222 return false;
2223
2224 return true;
2225}
2226
Johnny Chen60299ec2011-02-17 19:34:27 +00002227// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2228// A base register provides a pointer to the table, and a second register supplies an index into the table.
2229// The branch length is twice the value of the byte returned from the table.
2230//
2231// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2232// A base register provides a pointer to the table, and a second register supplies an index into the table.
2233// The branch length is twice the value of the halfword returned from the table.
2234// TBB, TBH
2235bool
2236EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2237{
2238#if 0
2239 // ARM pseudo code...
2240 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2241 if is_tbh then
2242 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2243 else
2244 halfwords = UInt(MemU[R[n]+R[m], 1]);
2245 BranchWritePC(PC + 2*halfwords);
2246#endif
2247
2248 bool success = false;
2249 const uint32_t opcode = OpcodeAsUnsigned (&success);
2250 if (!success)
2251 return false;
2252
2253 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2254 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2255 bool is_tbh; // true if table branch halfword
2256 switch (encoding) {
2257 case eEncodingT1:
2258 Rn = Bits32(opcode, 19, 16);
2259 Rm = Bits32(opcode, 3, 0);
2260 is_tbh = BitIsSet(opcode, 4);
2261 if (Rn == 13 || BadReg(Rm))
2262 return false;
2263 if (InITBlock() && !LastInITBlock())
2264 return false;
2265 break;
2266 default:
2267 return false;
2268 }
2269
2270 // Read the address of the table from the operand register Rn.
2271 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002272 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002273 if (!success)
2274 return false;
2275
2276 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002277 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002278 if (!success)
2279 return false;
2280
2281 // the offsetted table address
2282 addr_t addr = base + (is_tbh ? index*2 : index);
2283
2284 // PC-relative offset to branch forward
2285 EmulateInstruction::Context context;
2286 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002287 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002288 if (!success)
2289 return false;
2290
Johnny Chene39f22d2011-02-19 01:36:13 +00002291 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002292 if (!success)
2293 return false;
2294
2295 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002296 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002297 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2298 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2299
2300 if (!BranchWritePC(context, target))
2301 return false;
2302
2303 return true;
2304}
2305
Caroline Ticedcc11b32011-03-02 23:57:02 +00002306// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2307// It can optionally update the condition flags based on the result.
2308bool
2309EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2310{
2311#if 0
2312 if ConditionPassed() then
2313 EncodingSpecificOperations();
2314 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2315 R[d] = result;
2316 if setflags then
2317 APSR.N = result<31>;
2318 APSR.Z = IsZeroBit(result);
2319 APSR.C = carry;
2320 APSR.V = overflow;
2321#endif
2322
2323 bool success = false;
2324 const uint32_t opcode = OpcodeAsUnsigned (&success);
2325 if (!success)
2326 return false;
2327
2328 if (ConditionPassed())
2329 {
2330 uint32_t d;
2331 uint32_t n;
2332 bool setflags;
2333 uint32_t imm32;
2334 uint32_t carry_out;
2335
2336 //EncodingSpecificOperations();
2337 switch (encoding)
2338 {
2339 case eEncodingT1:
2340 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2341 d = Bits32 (opcode, 2, 0);
2342 n = Bits32 (opcode, 5, 3);
2343 setflags = !InITBlock();
2344 imm32 = Bits32 (opcode, 8,6);
2345
2346 break;
2347
2348 case eEncodingT2:
2349 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2350 d = Bits32 (opcode, 10, 8);
2351 n = Bits32 (opcode, 10, 8);
2352 setflags = !InITBlock();
2353 imm32 = Bits32 (opcode, 7, 0);
2354
2355 break;
2356
2357 case eEncodingT3:
2358 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2359 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2360 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2361 d = Bits32 (opcode, 11, 8);
2362 n = Bits32 (opcode, 19, 16);
2363 setflags = BitIsSet (opcode, 20);
2364 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2365
2366 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2367 if (BadReg (d) || (n == 15))
2368 return false;
2369
2370 break;
2371
2372 case eEncodingT4:
2373 {
2374 // if Rn == ’1111’ then SEE ADR;
2375 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2376 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2377 d = Bits32 (opcode, 11, 8);
2378 n = Bits32 (opcode, 19, 16);
2379 setflags = false;
2380 uint32_t i = Bit32 (opcode, 26);
2381 uint32_t imm3 = Bits32 (opcode, 14, 12);
2382 uint32_t imm8 = Bits32 (opcode, 7, 0);
2383 imm32 = (i << 11) | (imm3 << 8) | imm8;
2384
2385 // if BadReg(d) then UNPREDICTABLE;
2386 if (BadReg (d))
2387 return false;
2388
2389 break;
2390 }
2391 default:
2392 return false;
2393 }
2394
2395 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2396 if (!success)
2397 return false;
2398
2399 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2400 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2401
2402 Register reg_n;
2403 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2404
2405 EmulateInstruction::Context context;
2406 context.type = eContextAddition;
2407 context.SetRegisterPlusOffset (reg_n, imm32);
2408
2409 //R[d] = result;
2410 //if setflags then
2411 //APSR.N = result<31>;
2412 //APSR.Z = IsZeroBit(result);
2413 //APSR.C = carry;
2414 //APSR.V = overflow;
2415 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2416 return false;
2417
2418 }
2419 return true;
2420}
2421
Johnny Chen8fa20592011-02-18 01:22:22 +00002422// This instruction adds an immediate value to a register value, and writes the result to the destination
2423// register. It can optionally update the condition flags based on the result.
2424bool
2425EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2426{
2427#if 0
2428 // ARM pseudo code...
2429 if ConditionPassed() then
2430 EncodingSpecificOperations();
2431 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2432 if d == 15 then
2433 ALUWritePC(result); // setflags is always FALSE here
2434 else
2435 R[d] = result;
2436 if setflags then
2437 APSR.N = result<31>;
2438 APSR.Z = IsZeroBit(result);
2439 APSR.C = carry;
2440 APSR.V = overflow;
2441#endif
2442
2443 bool success = false;
2444 const uint32_t opcode = OpcodeAsUnsigned (&success);
2445 if (!success)
2446 return false;
2447
2448 if (ConditionPassed())
2449 {
2450 uint32_t Rd, Rn;
2451 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2452 bool setflags;
2453 switch (encoding)
2454 {
2455 case eEncodingA1:
2456 Rd = Bits32(opcode, 15, 12);
2457 Rn = Bits32(opcode, 19, 16);
2458 setflags = BitIsSet(opcode, 20);
2459 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2460 break;
2461 default:
2462 return false;
2463 }
2464
Johnny Chen8fa20592011-02-18 01:22:22 +00002465 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002466 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002467 if (!success)
2468 return false;
2469
2470 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2471
2472 EmulateInstruction::Context context;
2473 context.type = EmulateInstruction::eContextImmediate;
2474 context.SetNoArgs ();
2475
2476 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2477 return false;
2478 }
2479 return true;
2480}
2481
Johnny Chend761dcf2011-02-17 22:03:29 +00002482// This instruction adds a register value and an optionally-shifted register value, and writes the result
2483// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002484bool
Johnny Chen9f687722011-02-18 00:02:28 +00002485EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002486{
2487#if 0
2488 // ARM pseudo code...
2489 if ConditionPassed() then
2490 EncodingSpecificOperations();
2491 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2492 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2493 if d == 15 then
2494 ALUWritePC(result); // setflags is always FALSE here
2495 else
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 = overflow;
2502#endif
2503
2504 bool success = false;
2505 const uint32_t opcode = OpcodeAsUnsigned (&success);
2506 if (!success)
2507 return false;
2508
2509 if (ConditionPassed())
2510 {
2511 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002512 ARM_ShifterType shift_t;
2513 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002514 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002515 switch (encoding)
2516 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002517 case eEncodingT1:
2518 Rd = Bits32(opcode, 2, 0);
2519 Rn = Bits32(opcode, 5, 3);
2520 Rm = Bits32(opcode, 8, 6);
2521 setflags = !InITBlock();
2522 shift_t = SRType_LSL;
2523 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002524 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002525 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002526 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002527 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002528 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002529 shift_t = SRType_LSL;
2530 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002531 if (Rn == 15 && Rm == 15)
2532 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002533 if (Rd == 15 && InITBlock() && !LastInITBlock())
2534 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002535 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002536 case eEncodingA1:
2537 Rd = Bits32(opcode, 15, 12);
2538 Rn = Bits32(opcode, 19, 16);
2539 Rm = Bits32(opcode, 3, 0);
2540 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002541 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002542 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002543 default:
2544 return false;
2545 }
2546
Johnny Chen26863dc2011-02-09 23:43:29 +00002547 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002548 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002549 if (!success)
2550 return false;
2551
2552 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002553 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002554 if (!success)
2555 return false;
2556
Johnny Chene97c0d52011-02-18 19:32:20 +00002557 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002558 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002559
2560 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002561 context.type = EmulateInstruction::eContextAddition;
2562 Register op1_reg;
2563 Register op2_reg;
2564 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2565 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2566 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002567
Johnny Chen10530c22011-02-17 22:37:12 +00002568 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002569 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002570 }
2571 return true;
2572}
2573
Johnny Chen34075cb2011-02-22 01:56:31 +00002574// Compare Negative (immediate) adds a register value and an immediate value.
2575// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002576bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002577EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2578{
2579#if 0
2580 // ARM pseudo code...
2581 if ConditionPassed() then
2582 EncodingSpecificOperations();
2583 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2584 APSR.N = result<31>;
2585 APSR.Z = IsZeroBit(result);
2586 APSR.C = carry;
2587 APSR.V = overflow;
2588#endif
2589
2590 bool success = false;
2591 const uint32_t opcode = OpcodeAsUnsigned (&success);
2592 if (!success)
2593 return false;
2594
2595 uint32_t Rn; // the first operand
2596 uint32_t imm32; // the immediate value to be compared with
2597 switch (encoding) {
2598 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002599 Rn = Bits32(opcode, 19, 16);
2600 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2601 if (Rn == 15)
2602 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002603 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002604 case eEncodingA1:
2605 Rn = Bits32(opcode, 19, 16);
2606 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2607 break;
2608 default:
2609 return false;
2610 }
2611 // Read the register value from the operand register Rn.
2612 uint32_t reg_val = ReadCoreReg(Rn, &success);
2613 if (!success)
2614 return false;
2615
Johnny Chen078fbc62011-02-22 19:48:22 +00002616 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002617
2618 EmulateInstruction::Context context;
2619 context.type = EmulateInstruction::eContextImmediate;
2620 context.SetNoArgs ();
2621 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2622 return false;
2623
2624 return true;
2625}
2626
2627// Compare Negative (register) adds a register value and an optionally-shifted register value.
2628// It updates the condition flags based on the result, and discards the result.
2629bool
2630EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2631{
2632#if 0
2633 // ARM pseudo code...
2634 if ConditionPassed() then
2635 EncodingSpecificOperations();
2636 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2637 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2638 APSR.N = result<31>;
2639 APSR.Z = IsZeroBit(result);
2640 APSR.C = carry;
2641 APSR.V = overflow;
2642#endif
2643
2644 bool success = false;
2645 const uint32_t opcode = OpcodeAsUnsigned (&success);
2646 if (!success)
2647 return false;
2648
2649 uint32_t Rn; // the first operand
2650 uint32_t Rm; // the second operand
2651 ARM_ShifterType shift_t;
2652 uint32_t shift_n; // the shift applied to the value read from Rm
2653 switch (encoding) {
2654 case eEncodingT1:
2655 Rn = Bits32(opcode, 2, 0);
2656 Rm = Bits32(opcode, 5, 3);
2657 shift_t = SRType_LSL;
2658 shift_n = 0;
2659 break;
2660 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002661 Rn = Bits32(opcode, 19, 16);
2662 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002663 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002664 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2665 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002666 return false;
2667 break;
2668 case eEncodingA1:
2669 Rn = Bits32(opcode, 19, 16);
2670 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002671 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002672 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002673 default:
2674 return false;
2675 }
2676 // Read the register value from register Rn.
2677 uint32_t val1 = ReadCoreReg(Rn, &success);
2678 if (!success)
2679 return false;
2680
2681 // Read the register value from register Rm.
2682 uint32_t val2 = ReadCoreReg(Rm, &success);
2683 if (!success)
2684 return false;
2685
2686 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002687 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002688
2689 EmulateInstruction::Context context;
2690 context.type = EmulateInstruction::eContextImmediate;
2691 context.SetNoArgs();
2692 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2693 return false;
2694
2695 return true;
2696}
2697
2698// Compare (immediate) subtracts an immediate value from a register value.
2699// It updates the condition flags based on the result, and discards the result.
2700bool
2701EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002702{
2703#if 0
2704 // ARM pseudo code...
2705 if ConditionPassed() then
2706 EncodingSpecificOperations();
2707 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2708 APSR.N = result<31>;
2709 APSR.Z = IsZeroBit(result);
2710 APSR.C = carry;
2711 APSR.V = overflow;
2712#endif
2713
2714 bool success = false;
2715 const uint32_t opcode = OpcodeAsUnsigned (&success);
2716 if (!success)
2717 return false;
2718
2719 uint32_t Rn; // the first operand
2720 uint32_t imm32; // the immediate value to be compared with
2721 switch (encoding) {
2722 case eEncodingT1:
2723 Rn = Bits32(opcode, 10, 8);
2724 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002725 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002726 case eEncodingT2:
2727 Rn = Bits32(opcode, 19, 16);
2728 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2729 if (Rn == 15)
2730 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002731 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002732 case eEncodingA1:
2733 Rn = Bits32(opcode, 19, 16);
2734 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002735 break;
2736 default:
2737 return false;
2738 }
2739 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002740 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002741 if (!success)
2742 return false;
2743
Johnny Chen10530c22011-02-17 22:37:12 +00002744 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2745
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002746 EmulateInstruction::Context context;
2747 context.type = EmulateInstruction::eContextImmediate;
2748 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002749 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2750 return false;
2751
Johnny Chend4dc4442011-02-11 02:02:56 +00002752 return true;
2753}
2754
Johnny Chen34075cb2011-02-22 01:56:31 +00002755// Compare (register) subtracts an optionally-shifted register value from a register value.
2756// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002757bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002758EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002759{
2760#if 0
2761 // ARM pseudo code...
2762 if ConditionPassed() then
2763 EncodingSpecificOperations();
2764 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2765 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2766 APSR.N = result<31>;
2767 APSR.Z = IsZeroBit(result);
2768 APSR.C = carry;
2769 APSR.V = overflow;
2770#endif
2771
2772 bool success = false;
2773 const uint32_t opcode = OpcodeAsUnsigned (&success);
2774 if (!success)
2775 return false;
2776
2777 uint32_t Rn; // the first operand
2778 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002779 ARM_ShifterType shift_t;
2780 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002781 switch (encoding) {
2782 case eEncodingT1:
2783 Rn = Bits32(opcode, 2, 0);
2784 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002785 shift_t = SRType_LSL;
2786 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002787 break;
2788 case eEncodingT2:
2789 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2790 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002791 shift_t = SRType_LSL;
2792 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002793 if (Rn < 8 && Rm < 8)
2794 return false;
2795 if (Rn == 15 || Rm == 15)
2796 return false;
2797 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002798 case eEncodingA1:
2799 Rn = Bits32(opcode, 19, 16);
2800 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002801 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002802 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002803 default:
2804 return false;
2805 }
2806 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002807 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002808 if (!success)
2809 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002810
Johnny Chene4a4d302011-02-11 21:53:58 +00002811 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002812 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002813 if (!success)
2814 return false;
2815
Johnny Chen34075cb2011-02-22 01:56:31 +00002816 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2817 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002818
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002819 EmulateInstruction::Context context;
2820 context.type = EmulateInstruction::eContextImmediate;
2821 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002822 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2823 return false;
2824
Johnny Chene4a4d302011-02-11 21:53:58 +00002825 return true;
2826}
2827
Johnny Chen82f16aa2011-02-15 20:10:55 +00002828// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2829// shifting in copies of its sign bit, and writes the result to the destination register. It can
2830// optionally update the condition flags based on the result.
2831bool
2832EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2833{
2834#if 0
2835 // ARM pseudo code...
2836 if ConditionPassed() then
2837 EncodingSpecificOperations();
2838 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2839 if d == 15 then // Can only occur for ARM encoding
2840 ALUWritePC(result); // setflags is always FALSE here
2841 else
2842 R[d] = result;
2843 if setflags then
2844 APSR.N = result<31>;
2845 APSR.Z = IsZeroBit(result);
2846 APSR.C = carry;
2847 // APSR.V unchanged
2848#endif
2849
Johnny Chen41a0a152011-02-16 01:27:54 +00002850 return EmulateShiftImm(encoding, SRType_ASR);
2851}
2852
2853// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2854// shifting in copies of its sign bit, and writes the result to the destination register.
2855// The variable number of bits is read from the bottom byte of a register. It can optionally update
2856// the condition flags based on the result.
2857bool
2858EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2859{
2860#if 0
2861 // ARM pseudo code...
2862 if ConditionPassed() then
2863 EncodingSpecificOperations();
2864 shift_n = UInt(R[m]<7:0>);
2865 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2866 R[d] = result;
2867 if setflags then
2868 APSR.N = result<31>;
2869 APSR.Z = IsZeroBit(result);
2870 APSR.C = carry;
2871 // APSR.V unchanged
2872#endif
2873
2874 return EmulateShiftReg(encoding, SRType_ASR);
2875}
2876
2877// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2878// shifting in zeros, and writes the result to the destination register. It can optionally
2879// update the condition flags based on the result.
2880bool
2881EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2882{
2883#if 0
2884 // ARM pseudo code...
2885 if ConditionPassed() then
2886 EncodingSpecificOperations();
2887 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2888 if d == 15 then // Can only occur for ARM encoding
2889 ALUWritePC(result); // setflags is always FALSE here
2890 else
2891 R[d] = result;
2892 if setflags then
2893 APSR.N = result<31>;
2894 APSR.Z = IsZeroBit(result);
2895 APSR.C = carry;
2896 // APSR.V unchanged
2897#endif
2898
2899 return EmulateShiftImm(encoding, SRType_LSL);
2900}
2901
2902// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2903// shifting in zeros, and writes the result to the destination register. The variable number
2904// of bits is read from the bottom byte of a register. It can optionally update the condition
2905// flags based on the result.
2906bool
2907EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2908{
2909#if 0
2910 // ARM pseudo code...
2911 if ConditionPassed() then
2912 EncodingSpecificOperations();
2913 shift_n = UInt(R[m]<7:0>);
2914 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2915 R[d] = result;
2916 if setflags then
2917 APSR.N = result<31>;
2918 APSR.Z = IsZeroBit(result);
2919 APSR.C = carry;
2920 // APSR.V unchanged
2921#endif
2922
2923 return EmulateShiftReg(encoding, SRType_LSL);
2924}
2925
2926// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2927// shifting in zeros, and writes the result to the destination register. It can optionally
2928// update the condition flags based on the result.
2929bool
2930EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2931{
2932#if 0
2933 // ARM pseudo code...
2934 if ConditionPassed() then
2935 EncodingSpecificOperations();
2936 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2937 if d == 15 then // Can only occur for ARM encoding
2938 ALUWritePC(result); // setflags is always FALSE here
2939 else
2940 R[d] = result;
2941 if setflags then
2942 APSR.N = result<31>;
2943 APSR.Z = IsZeroBit(result);
2944 APSR.C = carry;
2945 // APSR.V unchanged
2946#endif
2947
2948 return EmulateShiftImm(encoding, SRType_LSR);
2949}
2950
2951// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2952// shifting in zeros, and writes the result to the destination register. The variable number
2953// of bits is read from the bottom byte of a register. It can optionally update the condition
2954// flags based on the result.
2955bool
2956EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2957{
2958#if 0
2959 // ARM pseudo code...
2960 if ConditionPassed() then
2961 EncodingSpecificOperations();
2962 shift_n = UInt(R[m]<7:0>);
2963 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2964 R[d] = result;
2965 if setflags then
2966 APSR.N = result<31>;
2967 APSR.Z = IsZeroBit(result);
2968 APSR.C = carry;
2969 // APSR.V unchanged
2970#endif
2971
2972 return EmulateShiftReg(encoding, SRType_LSR);
2973}
2974
Johnny Cheneeab4852011-02-16 22:14:44 +00002975// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2976// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2977// It can optionally update the condition flags based on the result.
2978bool
2979EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2980{
2981#if 0
2982 // ARM pseudo code...
2983 if ConditionPassed() then
2984 EncodingSpecificOperations();
2985 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2986 if d == 15 then // Can only occur for ARM encoding
2987 ALUWritePC(result); // setflags is always FALSE here
2988 else
2989 R[d] = result;
2990 if setflags then
2991 APSR.N = result<31>;
2992 APSR.Z = IsZeroBit(result);
2993 APSR.C = carry;
2994 // APSR.V unchanged
2995#endif
2996
2997 return EmulateShiftImm(encoding, SRType_ROR);
2998}
2999
3000// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3001// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3002// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3003// flags based on the result.
3004bool
3005EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
3006{
3007#if 0
3008 // ARM pseudo code...
3009 if ConditionPassed() then
3010 EncodingSpecificOperations();
3011 shift_n = UInt(R[m]<7:0>);
3012 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3013 R[d] = result;
3014 if setflags then
3015 APSR.N = result<31>;
3016 APSR.Z = IsZeroBit(result);
3017 APSR.C = carry;
3018 // APSR.V unchanged
3019#endif
3020
3021 return EmulateShiftReg(encoding, SRType_ROR);
3022}
3023
3024// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3025// with the carry flag shifted into bit [31].
3026//
3027// RRX can optionally update the condition flags based on the result.
3028// In that case, bit [0] is shifted into the carry flag.
3029bool
3030EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
3031{
3032#if 0
3033 // ARM pseudo code...
3034 if ConditionPassed() then
3035 EncodingSpecificOperations();
3036 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3037 if d == 15 then // Can only occur for ARM encoding
3038 ALUWritePC(result); // setflags is always FALSE here
3039 else
3040 R[d] = result;
3041 if setflags then
3042 APSR.N = result<31>;
3043 APSR.Z = IsZeroBit(result);
3044 APSR.C = carry;
3045 // APSR.V unchanged
3046#endif
3047
3048 return EmulateShiftImm(encoding, SRType_RRX);
3049}
3050
Johnny Chen41a0a152011-02-16 01:27:54 +00003051bool
3052EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
3053{
3054 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
3055
Johnny Chen82f16aa2011-02-15 20:10:55 +00003056 bool success = false;
3057 const uint32_t opcode = OpcodeAsUnsigned (&success);
3058 if (!success)
3059 return false;
3060
3061 if (ConditionPassed())
3062 {
Johnny Chene7f89532011-02-15 23:22:46 +00003063 uint32_t Rd; // the destination register
3064 uint32_t Rm; // the first operand register
3065 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003066 uint32_t carry; // the carry bit after the shift operation
3067 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003068
3069 // Special case handling!
3070 // A8.6.139 ROR (immediate) -- Encoding T1
3071 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3072 {
3073 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3074 // have the same decoding of bit fields as the other Thumb2 shift operations.
3075 encoding = eEncodingT2;
3076 }
3077
Johnny Chen82f16aa2011-02-15 20:10:55 +00003078 switch (encoding) {
3079 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003080 // Due to the above special case handling!
3081 assert(shift_type != SRType_ROR);
3082
Johnny Chen82f16aa2011-02-15 20:10:55 +00003083 Rd = Bits32(opcode, 2, 0);
3084 Rm = Bits32(opcode, 5, 3);
3085 setflags = !InITBlock();
3086 imm5 = Bits32(opcode, 10, 6);
3087 break;
3088 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003089 // A8.6.141 RRX
3090 assert(shift_type != SRType_RRX);
3091
Johnny Chen82f16aa2011-02-15 20:10:55 +00003092 Rd = Bits32(opcode, 11, 8);
3093 Rm = Bits32(opcode, 3, 0);
3094 setflags = BitIsSet(opcode, 20);
3095 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3096 if (BadReg(Rd) || BadReg(Rm))
3097 return false;
3098 break;
3099 case eEncodingA1:
3100 Rd = Bits32(opcode, 15, 12);
3101 Rm = Bits32(opcode, 3, 0);
3102 setflags = BitIsSet(opcode, 20);
3103 imm5 = Bits32(opcode, 11, 7);
3104 break;
3105 default:
3106 return false;
3107 }
3108
Johnny Cheneeab4852011-02-16 22:14:44 +00003109 // A8.6.139 ROR (immediate)
3110 if (shift_type == SRType_ROR && imm5 == 0)
3111 shift_type = SRType_RRX;
3112
Johnny Chen82f16aa2011-02-15 20:10:55 +00003113 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003114 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003115 if (!success)
3116 return false;
3117
Johnny Cheneeab4852011-02-16 22:14:44 +00003118 // Decode the shift amount if not RRX.
3119 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003120
Johnny Chene97c0d52011-02-18 19:32:20 +00003121 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003122
3123 // The context specifies that an immediate is to be moved into Rd.
3124 EmulateInstruction::Context context;
3125 context.type = EmulateInstruction::eContextImmediate;
3126 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003127
Johnny Chen10530c22011-02-17 22:37:12 +00003128 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003129 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003130 }
3131 return true;
3132}
3133
Johnny Chene7f89532011-02-15 23:22:46 +00003134bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003135EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003136{
Johnny Chen41a0a152011-02-16 01:27:54 +00003137 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003138
3139 bool success = false;
3140 const uint32_t opcode = OpcodeAsUnsigned (&success);
3141 if (!success)
3142 return false;
3143
3144 if (ConditionPassed())
3145 {
3146 uint32_t Rd; // the destination register
3147 uint32_t Rn; // the first operand register
3148 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3149 uint32_t carry; // the carry bit after the shift operation
3150 bool setflags;
3151 switch (encoding) {
3152 case eEncodingT1:
3153 Rd = Bits32(opcode, 2, 0);
3154 Rn = Rd;
3155 Rm = Bits32(opcode, 5, 3);
3156 setflags = !InITBlock();
3157 break;
3158 case eEncodingT2:
3159 Rd = Bits32(opcode, 11, 8);
3160 Rn = Bits32(opcode, 19, 16);
3161 Rm = Bits32(opcode, 3, 0);
3162 setflags = BitIsSet(opcode, 20);
3163 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3164 return false;
3165 break;
3166 case eEncodingA1:
3167 Rd = Bits32(opcode, 15, 12);
3168 Rn = Bits32(opcode, 3, 0);
3169 Rm = Bits32(opcode, 11, 8);
3170 setflags = BitIsSet(opcode, 20);
3171 if (Rd == 15 || Rn == 15 || Rm == 15)
3172 return false;
3173 break;
3174 default:
3175 return false;
3176 }
3177
3178 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003179 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003180 if (!success)
3181 return false;
3182 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003183 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003184 if (!success)
3185 return false;
3186
3187 // Get the shift amount.
3188 uint32_t amt = Bits32(val, 7, 0);
3189
Johnny Chene97c0d52011-02-18 19:32:20 +00003190 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003191
3192 // The context specifies that an immediate is to be moved into Rd.
3193 EmulateInstruction::Context context;
3194 context.type = EmulateInstruction::eContextImmediate;
3195 context.SetNoArgs ();
3196
Johnny Chen10530c22011-02-17 22:37:12 +00003197 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003198 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003199 }
3200 return true;
3201}
3202
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003203// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003204// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003205// can be written back to the base register.
3206bool
3207EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3208{
3209#if 0
3210 // ARM pseudo code...
3211 if ConditionPassed()
3212 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3213 address = R[n];
3214
3215 for i = 0 to 14
3216 if registers<i> == '1' then
3217 R[i] = MemA[address, 4]; address = address + 4;
3218 if registers<15> == '1' then
3219 LoadWritePC (MemA[address, 4]);
3220
3221 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3222 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3223
3224#endif
3225
3226 bool success = false;
3227 const uint32_t opcode = OpcodeAsUnsigned (&success);
3228 if (!success)
3229 return false;
3230
3231 if (ConditionPassed())
3232 {
3233 uint32_t n;
3234 uint32_t registers = 0;
3235 bool wback;
3236 const uint32_t addr_byte_size = GetAddressByteSize();
3237 switch (encoding)
3238 {
3239 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003240 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003241 n = Bits32 (opcode, 10, 8);
3242 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003243 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244 wback = BitIsClear (registers, n);
3245 // if BitCount(registers) < 1 then UNPREDICTABLE;
3246 if (BitCount(registers) < 1)
3247 return false;
3248 break;
3249 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003250 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3251 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003252 n = Bits32 (opcode, 19, 16);
3253 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003254 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003256
3257 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003258 if ((n == 15)
3259 || (BitCount (registers) < 2)
3260 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3261 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003262
3263 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003264 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003265 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003266
3267 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268 if (wback
3269 && BitIsSet (registers, n))
3270 return false;
3271 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003272
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003273 case eEncodingA1:
3274 n = Bits32 (opcode, 19, 16);
3275 registers = Bits32 (opcode, 15, 0);
3276 wback = BitIsSet (opcode, 21);
3277 if ((n == 15)
3278 || (BitCount (registers) < 1))
3279 return false;
3280 break;
3281 default:
3282 return false;
3283 }
3284
3285 int32_t offset = 0;
3286 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3287 if (!success)
3288 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003289
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003290 EmulateInstruction::Context context;
3291 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3292 Register dwarf_reg;
3293 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3294 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003295
3296 for (int i = 0; i < 14; ++i)
3297 {
3298 if (BitIsSet (registers, i))
3299 {
Caroline Tice85aab332011-02-08 23:56:10 +00003300 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003301 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302 if (wback && (n == 13)) // Pop Instruction
3303 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3304
3305 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003306 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003307 if (!success)
3308 return false;
3309
3310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3311 return false;
3312
3313 offset += addr_byte_size;
3314 }
3315 }
3316
3317 if (BitIsSet (registers, 15))
3318 {
3319 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003320 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003321 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003322 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003323 if (!success)
3324 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003325 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003326 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003327 return false;
3328 }
3329
3330 if (wback && BitIsClear (registers, n))
3331 {
Caroline Ticefa172202011-02-11 22:49:54 +00003332 // R[n] = R[n] + 4 * BitCount (registers)
3333 int32_t offset = addr_byte_size * BitCount (registers);
3334 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003335 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003336
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3338 return false;
3339 }
3340 if (wback && BitIsSet (registers, n))
3341 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003342 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003343 }
3344 return true;
3345}
Caroline Tice713c2662011-02-11 17:59:55 +00003346
3347// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3348// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3349// can optionally be written back tot he base registers.
3350bool
3351EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3352{
3353#if 0
3354 // ARM pseudo code...
3355 if ConditionPassed() then
3356 EncodingSpecificOperations();
3357 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003358
Caroline Tice713c2662011-02-11 17:59:55 +00003359 for i = 0 to 14
3360 if registers<i> == ’1’ then
3361 R[i] = MemA[address,4]; address = address + 4;
3362
3363 if registers<15> == ’1’ then
3364 LoadWritePC(MemA[address,4]);
3365
3366 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3367 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3368#endif
3369
3370 bool success = false;
3371 const uint32_t opcode = OpcodeAsUnsigned (&success);
3372 if (!success)
3373 return false;
3374
3375 if (ConditionPassed())
3376 {
3377 uint32_t n;
3378 uint32_t registers = 0;
3379 bool wback;
3380 const uint32_t addr_byte_size = GetAddressByteSize();
3381
3382 // EncodingSpecificOperations();
3383 switch (encoding)
3384 {
3385 case eEncodingA1:
3386 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3387 n = Bits32 (opcode, 19, 16);
3388 registers = Bits32 (opcode, 15, 0);
3389 wback = BitIsSet (opcode, 21);
3390
3391 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3392 if ((n == 15) || (BitCount (registers) < 1))
3393 return false;
3394
3395 break;
3396
3397 default:
3398 return false;
3399 }
3400 // address = R[n] - 4*BitCount(registers) + 4;
3401
3402 int32_t offset = 0;
3403 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3404
3405 if (!success)
3406 return false;
3407
3408 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3409
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003410 EmulateInstruction::Context context;
3411 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3412 Register dwarf_reg;
3413 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3414 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003415
3416 // for i = 0 to 14
3417 for (int i = 0; i < 14; ++i)
3418 {
3419 // if registers<i> == ’1’ then
3420 if (BitIsSet (registers, i))
3421 {
3422 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003423 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003424 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003425 if (!success)
3426 return false;
3427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3428 return false;
3429 offset += addr_byte_size;
3430 }
3431 }
3432
3433 // if registers<15> == ’1’ then
3434 // LoadWritePC(MemA[address,4]);
3435 if (BitIsSet (registers, 15))
3436 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003437 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003438 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003439 if (!success)
3440 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003441 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003442 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003443 return false;
3444 }
3445
3446 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3447 if (wback && BitIsClear (registers, n))
3448 {
Caroline Tice713c2662011-02-11 17:59:55 +00003449 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3450 if (!success)
3451 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003452
3453 offset = (addr_byte_size * BitCount (registers)) * -1;
3454 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003455 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003456 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003457 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3458 return false;
3459 }
3460
3461 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3462 if (wback && BitIsSet (registers, n))
3463 return WriteBits32Unknown (n);
3464 }
3465 return true;
3466}
3467
3468// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3469// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3470// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003471bool
3472EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3473{
3474#if 0
3475 // ARM pseudo code...
3476 if ConditionPassed() then
3477 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3478 address = R[n] - 4*BitCount(registers);
3479
3480 for i = 0 to 14
3481 if registers<i> == ’1’ then
3482 R[i] = MemA[address,4]; address = address + 4;
3483 if registers<15> == ’1’ then
3484 LoadWritePC(MemA[address,4]);
3485
3486 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3487 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3488#endif
3489
3490 bool success = false;
3491 const uint32_t opcode = OpcodeAsUnsigned (&success);
3492 if (!success)
3493 return false;
3494
3495 if (ConditionPassed())
3496 {
3497 uint32_t n;
3498 uint32_t registers = 0;
3499 bool wback;
3500 const uint32_t addr_byte_size = GetAddressByteSize();
3501 switch (encoding)
3502 {
3503 case eEncodingT1:
3504 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3505 n = Bits32 (opcode, 19, 16);
3506 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003507 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003508 wback = BitIsSet (opcode, 21);
3509
3510 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3511 if ((n == 15)
3512 || (BitCount (registers) < 2)
3513 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3514 return false;
3515
3516 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003517 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003518 return false;
3519
3520 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3521 if (wback && BitIsSet (registers, n))
3522 return false;
3523
3524 break;
3525
3526 case eEncodingA1:
3527 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3528 n = Bits32 (opcode, 19, 16);
3529 registers = Bits32 (opcode, 15, 0);
3530 wback = BitIsSet (opcode, 21);
3531
3532 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3533 if ((n == 15) || (BitCount (registers) < 1))
3534 return false;
3535
3536 break;
3537
3538 default:
3539 return false;
3540 }
3541
Caroline Tice713c2662011-02-11 17:59:55 +00003542 // address = R[n] - 4*BitCount(registers);
3543
Caroline Tice0b29e242011-02-08 23:16:02 +00003544 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003545 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3546
3547 if (!success)
3548 return false;
3549
3550 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003551 EmulateInstruction::Context context;
3552 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3553 Register dwarf_reg;
3554 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3555 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003556
3557 for (int i = 0; i < 14; ++i)
3558 {
3559 if (BitIsSet (registers, i))
3560 {
3561 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003562 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003563 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003564 if (!success)
3565 return false;
3566
3567 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3568 return false;
3569
3570 offset += addr_byte_size;
3571 }
3572 }
3573
3574 // if registers<15> == ’1’ then
3575 // LoadWritePC(MemA[address,4]);
3576 if (BitIsSet (registers, 15))
3577 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003578 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003579 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003580 if (!success)
3581 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003582 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003583 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003584 return false;
3585 }
3586
3587 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3588 if (wback && BitIsClear (registers, n))
3589 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003590 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3591 if (!success)
3592 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003593
3594 offset = (addr_byte_size * BitCount (registers)) * -1;
3595 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003596 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003597 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3599 return false;
3600 }
3601
3602 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3603 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003604 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003605 }
3606 return true;
3607}
Caroline Tice85aab332011-02-08 23:56:10 +00003608
Caroline Tice713c2662011-02-11 17:59:55 +00003609// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3610// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3611// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003612bool
3613EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3614{
3615#if 0
3616 if ConditionPassed() then
3617 EncodingSpecificOperations();
3618 address = R[n] + 4;
3619
3620 for i = 0 to 14
3621 if registers<i> == ’1’ then
3622 R[i] = MemA[address,4]; address = address + 4;
3623 if registers<15> == ’1’ then
3624 LoadWritePC(MemA[address,4]);
3625
3626 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3627 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3628#endif
3629
3630 bool success = false;
3631 const uint32_t opcode = OpcodeAsUnsigned (&success);
3632 if (!success)
3633 return false;
3634
3635 if (ConditionPassed())
3636 {
3637 uint32_t n;
3638 uint32_t registers = 0;
3639 bool wback;
3640 const uint32_t addr_byte_size = GetAddressByteSize();
3641 switch (encoding)
3642 {
3643 case eEncodingA1:
3644 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3645 n = Bits32 (opcode, 19, 16);
3646 registers = Bits32 (opcode, 15, 0);
3647 wback = BitIsSet (opcode, 21);
3648
3649 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3650 if ((n == 15) || (BitCount (registers) < 1))
3651 return false;
3652
3653 break;
3654 default:
3655 return false;
3656 }
3657 // address = R[n] + 4;
3658
3659 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003660 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3661
3662 if (!success)
3663 return false;
3664
3665 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003666
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003667 EmulateInstruction::Context context;
3668 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3669 Register dwarf_reg;
3670 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3671 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003672
3673 for (int i = 0; i < 14; ++i)
3674 {
3675 if (BitIsSet (registers, i))
3676 {
3677 // R[i] = MemA[address,4]; address = address + 4;
3678
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003679 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003680 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003681 if (!success)
3682 return false;
3683
3684 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3685 return false;
3686
3687 offset += addr_byte_size;
3688 }
3689 }
3690
3691 // if registers<15> == ’1’ then
3692 // LoadWritePC(MemA[address,4]);
3693 if (BitIsSet (registers, 15))
3694 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003695 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003696 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003697 if (!success)
3698 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003699 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003700 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003701 return false;
3702 }
3703
3704 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3705 if (wback && BitIsClear (registers, n))
3706 {
Caroline Tice85aab332011-02-08 23:56:10 +00003707 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3708 if (!success)
3709 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003710
3711 offset = addr_byte_size * BitCount (registers);
3712 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003713 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003714 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003715 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3716 return false;
3717 }
3718
3719 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3720 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003721 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003722 }
3723 return true;
3724}
Caroline Tice0b29e242011-02-08 23:16:02 +00003725
Johnny Chenef21b592011-02-10 01:52:38 +00003726// Load Register (immediate) calculates an address from a base register value and
3727// an immediate offset, loads a word from memory, and writes to a register.
3728// LDR (immediate, Thumb)
3729bool
3730EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3731{
3732#if 0
3733 // ARM pseudo code...
3734 if (ConditionPassed())
3735 {
3736 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3737 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3738 address = if index then offset_addr else R[n];
3739 data = MemU[address,4];
3740 if wback then R[n] = offset_addr;
3741 if t == 15 then
3742 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3743 elsif UnalignedSupport() || address<1:0> = '00' then
3744 R[t] = data;
3745 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3746 }
3747#endif
3748
3749 bool success = false;
3750 const uint32_t opcode = OpcodeAsUnsigned (&success);
3751 if (!success)
3752 return false;
3753
3754 if (ConditionPassed())
3755 {
3756 uint32_t Rt; // the destination register
3757 uint32_t Rn; // the base register
3758 uint32_t imm32; // the immediate offset used to form the address
3759 addr_t offset_addr; // the offset address
3760 addr_t address; // the calculated address
3761 uint32_t data; // the literal data value from memory load
3762 bool add, index, wback;
3763 switch (encoding) {
3764 case eEncodingT1:
3765 Rt = Bits32(opcode, 5, 3);
3766 Rn = Bits32(opcode, 2, 0);
3767 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3768 // index = TRUE; add = TRUE; wback = FALSE
3769 add = true;
3770 index = true;
3771 wback = false;
3772 break;
3773 default:
3774 return false;
3775 }
3776 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3777 if (!success)
3778 return false;
3779 if (add)
3780 offset_addr = base + imm32;
3781 else
3782 offset_addr = base - imm32;
3783
3784 address = (index ? offset_addr : base);
3785
3786 if (wback)
3787 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003788 EmulateInstruction::Context ctx;
3789 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3790 Register dwarf_reg;
3791 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3792 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3793
Johnny Chenef21b592011-02-10 01:52:38 +00003794 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3795 return false;
3796 }
3797
3798 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003799 EmulateInstruction::Context context;
3800 context.type = EmulateInstruction::eContextImmediate;
3801 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003802
3803 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003804 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003805 if (!success)
3806 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003807
3808 if (Rt == 15)
3809 {
3810 if (Bits32(address, 1, 0) == 0)
3811 {
Johnny Chen668b4512011-02-15 21:08:58 +00003812 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003813 return false;
3814 }
3815 else
3816 return false;
3817 }
3818 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3819 {
3820 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3821 return false;
3822 }
3823 else
3824 return false;
3825 }
3826 return true;
3827}
3828
Caroline Ticeaf556562011-02-15 18:42:15 +00003829// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3830// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3831// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003832bool
3833EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3834{
3835#if 0
3836 if ConditionPassed() then
3837 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3838 address = R[n];
3839
3840 for i = 0 to 14
3841 if registers<i> == ’1’ then
3842 if i == n && wback && i != LowestSetBit(registers) then
3843 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3844 else
3845 MemA[address,4] = R[i];
3846 address = address + 4;
3847
3848 if registers<15> == ’1’ then // Only possible for encoding A1
3849 MemA[address,4] = PCStoreValue();
3850 if wback then R[n] = R[n] + 4*BitCount(registers);
3851#endif
3852
3853 bool success = false;
3854 const uint32_t opcode = OpcodeAsUnsigned (&success);
3855 if (!success)
3856 return false;
3857
3858 if (ConditionPassed ())
3859 {
3860 uint32_t n;
3861 uint32_t registers = 0;
3862 bool wback;
3863 const uint32_t addr_byte_size = GetAddressByteSize();
3864
3865 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3866 switch (encoding)
3867 {
3868 case eEncodingT1:
3869 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3870 n = Bits32 (opcode, 10, 8);
3871 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003872 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003873 wback = true;
3874
3875 // if BitCount(registers) < 1 then UNPREDICTABLE;
3876 if (BitCount (registers) < 1)
3877 return false;
3878
3879 break;
3880
3881 case eEncodingT2:
3882 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3883 n = Bits32 (opcode, 19, 16);
3884 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003885 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003886 wback = BitIsSet (opcode, 21);
3887
3888 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3889 if ((n == 15) || (BitCount (registers) < 2))
3890 return false;
3891
3892 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3893 if (wback && BitIsSet (registers, n))
3894 return false;
3895
3896 break;
3897
3898 case eEncodingA1:
3899 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3900 n = Bits32 (opcode, 19, 16);
3901 registers = Bits32 (opcode, 15, 0);
3902 wback = BitIsSet (opcode, 21);
3903
3904 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3905 if ((n == 15) || (BitCount (registers) < 1))
3906 return false;
3907
3908 break;
3909
3910 default:
3911 return false;
3912 }
3913
3914 // address = R[n];
3915 int32_t offset = 0;
3916 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3917 if (!success)
3918 return false;
3919
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003920 EmulateInstruction::Context context;
3921 context.type = EmulateInstruction::eContextRegisterStore;
3922 Register base_reg;
3923 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003924
3925 // for i = 0 to 14
3926 for (int i = 0; i < 14; ++i)
3927 {
3928 int lowest_set_bit = 14;
3929 // if registers<i> == ’1’ then
3930 if (BitIsSet (registers, i))
3931 {
3932 if (i < lowest_set_bit)
3933 lowest_set_bit = i;
3934 // if i == n && wback && i != LowestSetBit(registers) then
3935 if ((i == n) && wback && (i != lowest_set_bit))
3936 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3937 WriteBits32UnknownToMemory (address + offset);
3938 else
3939 {
3940 // MemA[address,4] = R[i];
3941 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3942 if (!success)
3943 return false;
3944
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003945 Register data_reg;
3946 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3947 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003948 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003949 return false;
3950 }
3951
3952 // address = address + 4;
3953 offset += addr_byte_size;
3954 }
3955 }
3956
3957 // if registers<15> == ’1’ then // Only possible for encoding A1
3958 // MemA[address,4] = PCStoreValue();
3959 if (BitIsSet (registers, 15))
3960 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003961 Register pc_reg;
3962 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3963 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003964 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003965 if (!success)
3966 return false;
3967
Caroline Tice8d681f52011-03-17 23:50:16 +00003968 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003969 return false;
3970 }
3971
3972 // if wback then R[n] = R[n] + 4*BitCount(registers);
3973 if (wback)
3974 {
3975 offset = addr_byte_size * BitCount (registers);
3976 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003977 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003978 addr_t data = address + offset;
3979 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3980 return false;
3981 }
3982 }
3983 return true;
3984}
3985
Caroline Ticeaf556562011-02-15 18:42:15 +00003986// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3987// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3988// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003989bool
3990EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3991{
3992#if 0
3993 if ConditionPassed() then
3994 EncodingSpecificOperations();
3995 address = R[n] - 4*BitCount(registers) + 4;
3996
3997 for i = 0 to 14
3998 if registers<i> == ’1’ then
3999 if i == n && wback && i != LowestSetBit(registers) then
4000 MemA[address,4] = bits(32) UNKNOWN;
4001 else
4002 MemA[address,4] = R[i];
4003 address = address + 4;
4004
4005 if registers<15> == ’1’ then
4006 MemA[address,4] = PCStoreValue();
4007
4008 if wback then R[n] = R[n] - 4*BitCount(registers);
4009#endif
4010
4011 bool success = false;
4012 const uint32_t opcode = OpcodeAsUnsigned (&success);
4013 if (!success)
4014 return false;
4015
4016 if (ConditionPassed ())
4017 {
4018 uint32_t n;
4019 uint32_t registers = 0;
4020 bool wback;
4021 const uint32_t addr_byte_size = GetAddressByteSize();
4022
4023 // EncodingSpecificOperations();
4024 switch (encoding)
4025 {
4026 case eEncodingA1:
4027 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4028 n = Bits32 (opcode, 19, 16);
4029 registers = Bits32 (opcode, 15, 0);
4030 wback = BitIsSet (opcode, 21);
4031
4032 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4033 if ((n == 15) || (BitCount (registers) < 1))
4034 return false;
4035 break;
4036 default:
4037 return false;
4038 }
4039
4040 // address = R[n] - 4*BitCount(registers) + 4;
4041 int32_t offset = 0;
4042 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4043 if (!success)
4044 return false;
4045
4046 address = address - (addr_byte_size * BitCount (registers)) + 4;
4047
4048 EmulateInstruction::Context context;
4049 context.type = EmulateInstruction::eContextRegisterStore;
4050 Register base_reg;
4051 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4052
4053 // for i = 0 to 14
4054 for (int i = 0; i < 14; ++i)
4055 {
4056 int lowest_bit_set = 14;
4057 // if registers<i> == ’1’ then
4058 if (BitIsSet (registers, i))
4059 {
4060 if (i < lowest_bit_set)
4061 lowest_bit_set = i;
4062 //if i == n && wback && i != LowestSetBit(registers) then
4063 if ((i == n) && wback && (i != lowest_bit_set))
4064 // MemA[address,4] = bits(32) UNKNOWN;
4065 WriteBits32UnknownToMemory (address + offset);
4066 else
4067 {
4068 // MemA[address,4] = R[i];
4069 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4070 if (!success)
4071 return false;
4072
4073 Register data_reg;
4074 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4075 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004076 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004077 return false;
4078 }
4079
4080 // address = address + 4;
4081 offset += addr_byte_size;
4082 }
4083 }
4084
4085 // if registers<15> == ’1’ then
4086 // MemA[address,4] = PCStoreValue();
4087 if (BitIsSet (registers, 15))
4088 {
4089 Register pc_reg;
4090 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4091 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004092 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004093 if (!success)
4094 return false;
4095
Caroline Tice8d681f52011-03-17 23:50:16 +00004096 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004097 return false;
4098 }
4099
4100 // if wback then R[n] = R[n] - 4*BitCount(registers);
4101 if (wback)
4102 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004103 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004104 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4105 context.SetImmediateSigned (offset);
4106 addr_t data = address + offset;
4107 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4108 return false;
4109 }
4110 }
4111 return true;
4112}
4113
Caroline Ticeaf556562011-02-15 18:42:15 +00004114// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4115// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4116// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004117bool
4118EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4119{
4120#if 0
4121 if ConditionPassed() then
4122 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4123 address = R[n] - 4*BitCount(registers);
4124
4125 for i = 0 to 14
4126 if registers<i> == ’1’ then
4127 if i == n && wback && i != LowestSetBit(registers) then
4128 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4129 else
4130 MemA[address,4] = R[i];
4131 address = address + 4;
4132
4133 if registers<15> == ’1’ then // Only possible for encoding A1
4134 MemA[address,4] = PCStoreValue();
4135
4136 if wback then R[n] = R[n] - 4*BitCount(registers);
4137#endif
4138
4139
4140 bool success = false;
4141 const uint32_t opcode = OpcodeAsUnsigned (&success);
4142 if (!success)
4143 return false;
4144
4145 if (ConditionPassed ())
4146 {
4147 uint32_t n;
4148 uint32_t registers = 0;
4149 bool wback;
4150 const uint32_t addr_byte_size = GetAddressByteSize();
4151
4152 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4153 switch (encoding)
4154 {
4155 case eEncodingT1:
4156 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4157 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4158 {
4159 // See PUSH
4160 }
4161 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4162 n = Bits32 (opcode, 19, 16);
4163 registers = Bits32 (opcode, 15, 0);
4164 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4165 wback = BitIsSet (opcode, 21);
4166 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4167 if ((n == 15) || BitCount (registers) < 2)
4168 return false;
4169 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4170 if (wback && BitIsSet (registers, n))
4171 return false;
4172 break;
4173
4174 case eEncodingA1:
4175 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4176 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4177 {
4178 // See Push
4179 }
4180 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4181 n = Bits32 (opcode, 19, 16);
4182 registers = Bits32 (opcode, 15, 0);
4183 wback = BitIsSet (opcode, 21);
4184 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4185 if ((n == 15) || BitCount (registers) < 1)
4186 return false;
4187 break;
4188
4189 default:
4190 return false;
4191 }
4192
4193 // address = R[n] - 4*BitCount(registers);
4194
4195 int32_t offset = 0;
4196 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4197 if (!success)
4198 return false;
4199
4200 address = address - (addr_byte_size * BitCount (registers));
4201
4202 EmulateInstruction::Context context;
4203 context.type = EmulateInstruction::eContextRegisterStore;
4204 Register base_reg;
4205 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4206
4207 // for i = 0 to 14
4208 for (int i = 0; i < 14; ++i)
4209 {
4210 uint32_t lowest_set_bit = 14;
4211 // if registers<i> == ’1’ then
4212 if (BitIsSet (registers, i))
4213 {
4214 if (i < lowest_set_bit)
4215 lowest_set_bit = i;
4216 // if i == n && wback && i != LowestSetBit(registers) then
4217 if ((i == n) && wback && (i != lowest_set_bit))
4218 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4219 WriteBits32UnknownToMemory (address + offset);
4220 else
4221 {
4222 // MemA[address,4] = R[i];
4223 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4224 if (!success)
4225 return false;
4226
4227 Register data_reg;
4228 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4229 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004230 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004231 return false;
4232 }
4233
4234 // address = address + 4;
4235 offset += addr_byte_size;
4236 }
4237 }
4238
4239 // if registers<15> == ’1’ then // Only possible for encoding A1
4240 // MemA[address,4] = PCStoreValue();
4241 if (BitIsSet (registers, 15))
4242 {
4243 Register pc_reg;
4244 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4245 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004246 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004247 if (!success)
4248 return false;
4249
Caroline Tice8d681f52011-03-17 23:50:16 +00004250 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004251 return false;
4252 }
4253
4254 // if wback then R[n] = R[n] - 4*BitCount(registers);
4255 if (wback)
4256 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004257 offset = (addr_byte_size * BitCount (registers)) * -1;
4258 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4259 context.SetImmediateSigned (offset);
4260 addr_t data = address + offset;
4261 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4262 return false;
4263 }
4264 }
4265 return true;
4266}
4267
4268// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4269// from a base register. The consecutive memory locations start just above this address, and the address of the last
4270// of those locations can optionally be written back to the base register.
4271bool
4272EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4273{
4274#if 0
4275 if ConditionPassed() then
4276 EncodingSpecificOperations();
4277 address = R[n] + 4;
4278
4279 for i = 0 to 14
4280 if registers<i> == ’1’ then
4281 if i == n && wback && i != LowestSetBit(registers) then
4282 MemA[address,4] = bits(32) UNKNOWN;
4283 else
4284 MemA[address,4] = R[i];
4285 address = address + 4;
4286
4287 if registers<15> == ’1’ then
4288 MemA[address,4] = PCStoreValue();
4289
4290 if wback then R[n] = R[n] + 4*BitCount(registers);
4291#endif
4292
4293 bool success = false;
4294 const uint32_t opcode = OpcodeAsUnsigned (&success);
4295 if (!success)
4296 return false;
4297
4298 if (ConditionPassed())
4299 {
4300 uint32_t n;
4301 uint32_t registers = 0;
4302 bool wback;
4303 const uint32_t addr_byte_size = GetAddressByteSize();
4304
4305 // EncodingSpecificOperations();
4306 switch (encoding)
4307 {
4308 case eEncodingA1:
4309 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4310 n = Bits32 (opcode, 19, 16);
4311 registers = Bits32 (opcode, 15, 0);
4312 wback = BitIsSet (opcode, 21);
4313
4314 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4315 if ((n == 15) && (BitCount (registers) < 1))
4316 return false;
4317 break;
4318 default:
4319 return false;
4320 }
4321 // address = R[n] + 4;
4322
4323 int32_t offset = 0;
4324 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4325 if (!success)
4326 return false;
4327
4328 address = address + addr_byte_size;
4329
4330 EmulateInstruction::Context context;
4331 context.type = EmulateInstruction::eContextRegisterStore;
4332 Register base_reg;
4333 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4334
4335 uint32_t lowest_set_bit = 14;
4336 // for i = 0 to 14
4337 for (int i = 0; i < 14; ++i)
4338 {
4339 // if registers<i> == ’1’ then
4340 if (BitIsSet (registers, i))
4341 {
4342 if (i < lowest_set_bit)
4343 lowest_set_bit = i;
4344 // if i == n && wback && i != LowestSetBit(registers) then
4345 if ((i == n) && wback && (i != lowest_set_bit))
4346 // MemA[address,4] = bits(32) UNKNOWN;
4347 WriteBits32UnknownToMemory (address + offset);
4348 // else
4349 else
4350 {
4351 // MemA[address,4] = R[i];
4352 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4353 if (!success)
4354 return false;
4355
4356 Register data_reg;
4357 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4358 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004359 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004360 return false;
4361 }
4362
4363 // address = address + 4;
4364 offset += addr_byte_size;
4365 }
4366 }
4367
4368 // if registers<15> == ’1’ then
4369 // MemA[address,4] = PCStoreValue();
4370 if (BitIsSet (registers, 15))
4371 {
4372 Register pc_reg;
4373 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4374 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004375 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004376 if (!success)
4377 return false;
4378
Caroline Tice8d681f52011-03-17 23:50:16 +00004379 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004380 return false;
4381 }
4382
4383 // if wback then R[n] = R[n] + 4*BitCount(registers);
4384 if (wback)
4385 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004386 offset = addr_byte_size * BitCount (registers);
4387 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4388 context.SetImmediateSigned (offset);
4389 addr_t data = address + offset;
4390 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4391 return false;
4392 }
4393 }
4394 return true;
4395}
Caroline Tice7fac8572011-02-15 22:53:54 +00004396
4397// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4398// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4399bool
4400EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4401{
4402#if 0
4403 if ConditionPassed() then
4404 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4405 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4406 address = if index then offset_addr else R[n];
4407 if UnalignedSupport() || address<1:0> == ’00’ then
4408 MemU[address,4] = R[t];
4409 else // Can only occur before ARMv7
4410 MemU[address,4] = bits(32) UNKNOWN;
4411 if wback then R[n] = offset_addr;
4412#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004413
Caroline Tice7fac8572011-02-15 22:53:54 +00004414 bool success = false;
4415 const uint32_t opcode = OpcodeAsUnsigned (&success);
4416 if (!success)
4417 return false;
4418
4419 if (ConditionPassed())
4420 {
4421 const uint32_t addr_byte_size = GetAddressByteSize();
4422
4423 uint32_t t;
4424 uint32_t n;
4425 uint32_t imm32;
4426 bool index;
4427 bool add;
4428 bool wback;
4429 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4430 switch (encoding)
4431 {
4432 case eEncodingT1:
4433 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4434 t = Bits32 (opcode, 2, 0);
4435 n = Bits32 (opcode, 5, 3);
4436 imm32 = Bits32 (opcode, 10, 6) << 2;
4437
4438 // index = TRUE; add = TRUE; wback = FALSE;
4439 index = true;
4440 add = false;
4441 wback = false;
4442 break;
4443
4444 case eEncodingT2:
4445 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4446 t = Bits32 (opcode, 10, 8);
4447 n = 13;
4448 imm32 = Bits32 (opcode, 7, 0) << 2;
4449
4450 // index = TRUE; add = TRUE; wback = FALSE;
4451 index = true;
4452 add = true;
4453 wback = false;
4454 break;
4455
4456 case eEncodingT3:
4457 // if Rn == ’1111’ then UNDEFINED;
4458 if (Bits32 (opcode, 19, 16) == 15)
4459 return false;
4460
4461 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4462 t = Bits32 (opcode, 15, 12);
4463 n = Bits32 (opcode, 19, 16);
4464 imm32 = Bits32 (opcode, 11, 0);
4465
4466 // index = TRUE; add = TRUE; wback = FALSE;
4467 index = true;
4468 add = true;
4469 wback = false;
4470
4471 // if t == 15 then UNPREDICTABLE;
4472 if (t == 15)
4473 return false;
4474 break;
4475
4476 case eEncodingT4:
4477 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4478 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4479 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4480 if ((Bits32 (opcode, 19, 16) == 15)
4481 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4482 return false;
4483
4484 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4485 t = Bits32 (opcode, 15, 12);
4486 n = Bits32 (opcode, 19, 16);
4487 imm32 = Bits32 (opcode, 7, 0);
4488
4489 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4490 index = BitIsSet (opcode, 10);
4491 add = BitIsSet (opcode, 9);
4492 wback = BitIsSet (opcode, 8);
4493
4494 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4495 if ((t == 15) || (wback && (n == t)))
4496 return false;
4497 break;
4498
4499 default:
4500 return false;
4501 }
4502
4503 addr_t offset_addr;
4504 addr_t address;
4505
4506 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4507 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4508 if (!success)
4509 return false;
4510
4511 if (add)
4512 offset_addr = base_address + imm32;
4513 else
4514 offset_addr = base_address - imm32;
4515
4516 // address = if index then offset_addr else R[n];
4517 if (index)
4518 address = offset_addr;
4519 else
4520 address = base_address;
4521
4522 EmulateInstruction::Context context;
4523 context.type = eContextRegisterStore;
4524 Register base_reg;
4525 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4526
4527 // if UnalignedSupport() || address<1:0> == ’00’ then
4528 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4529 {
4530 // MemU[address,4] = R[t];
4531 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4532 if (!success)
4533 return false;
4534
4535 Register data_reg;
4536 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4537 int32_t offset = address - base_address;
4538 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004539 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004540 return false;
4541 }
4542 else
4543 {
4544 // MemU[address,4] = bits(32) UNKNOWN;
4545 WriteBits32UnknownToMemory (address);
4546 }
4547
4548 // if wback then R[n] = offset_addr;
4549 if (wback)
4550 {
4551 context.type = eContextRegisterLoad;
4552 context.SetAddress (offset_addr);
4553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4554 return false;
4555 }
4556 }
4557 return true;
4558}
Caroline Ticeaf556562011-02-15 18:42:15 +00004559
Caroline Tice3fd63e92011-02-16 00:33:43 +00004560// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4561// word from a register to memory. The offset register value can optionally be shifted.
4562bool
4563EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4564{
4565#if 0
4566 if ConditionPassed() then
4567 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4568 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4569 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4570 address = if index then offset_addr else R[n];
4571 if t == 15 then // Only possible for encoding A1
4572 data = PCStoreValue();
4573 else
4574 data = R[t];
4575 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4576 MemU[address,4] = data;
4577 else // Can only occur before ARMv7
4578 MemU[address,4] = bits(32) UNKNOWN;
4579 if wback then R[n] = offset_addr;
4580#endif
4581
4582 bool success = false;
4583 const uint32_t opcode = OpcodeAsUnsigned (&success);
4584 if (!success)
4585 return false;
4586
4587 if (ConditionPassed())
4588 {
4589 const uint32_t addr_byte_size = GetAddressByteSize();
4590
4591 uint32_t t;
4592 uint32_t n;
4593 uint32_t m;
4594 ARM_ShifterType shift_t;
4595 uint32_t shift_n;
4596 bool index;
4597 bool add;
4598 bool wback;
4599
4600 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4601 switch (encoding)
4602 {
4603 case eEncodingT1:
4604 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4605 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4606 t = Bits32 (opcode, 2, 0);
4607 n = Bits32 (opcode, 5, 3);
4608 m = Bits32 (opcode, 8, 6);
4609
4610 // index = TRUE; add = TRUE; wback = FALSE;
4611 index = true;
4612 add = true;
4613 wback = false;
4614
4615 // (shift_t, shift_n) = (SRType_LSL, 0);
4616 shift_t = SRType_LSL;
4617 shift_n = 0;
4618 break;
4619
4620 case eEncodingT2:
4621 // if Rn == ’1111’ then UNDEFINED;
4622 if (Bits32 (opcode, 19, 16) == 15)
4623 return false;
4624
4625 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4626 t = Bits32 (opcode, 15, 12);
4627 n = Bits32 (opcode, 19, 16);
4628 m = Bits32 (opcode, 3, 0);
4629
4630 // index = TRUE; add = TRUE; wback = FALSE;
4631 index = true;
4632 add = true;
4633 wback = false;
4634
4635 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4636 shift_t = SRType_LSL;
4637 shift_n = Bits32 (opcode, 5, 4);
4638
4639 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4640 if ((t == 15) || (BadReg (m)))
4641 return false;
4642 break;
4643
4644 case eEncodingA1:
4645 {
4646 // if P == ’0’ && W == ’1’ then SEE STRT;
4647 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4648 t = Bits32 (opcode, 15, 12);
4649 n = Bits32 (opcode, 19, 16);
4650 m = Bits32 (opcode, 3, 0);
4651
4652 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4653 index = BitIsSet (opcode, 24);
4654 add = BitIsSet (opcode, 23);
4655 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4656
4657 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4658 uint32_t typ = Bits32 (opcode, 6, 5);
4659 uint32_t imm5 = Bits32 (opcode, 11, 7);
4660 shift_n = DecodeImmShift(typ, imm5, shift_t);
4661
4662 // if m == 15 then UNPREDICTABLE;
4663 if (m == 15)
4664 return false;
4665
4666 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4667 if (wback && ((n == 15) || (n == t)))
4668 return false;
4669
4670 break;
4671 }
4672 default:
4673 return false;
4674 }
4675
4676 addr_t offset_addr;
4677 addr_t address;
4678 int32_t offset = 0;
4679
4680 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4681 if (!success)
4682 return false;
4683
4684 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4685 if (!success)
4686 return false;
4687
4688 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004689 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004690
4691 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4692 if (add)
4693 offset_addr = base_address + offset;
4694 else
4695 offset_addr = base_address - offset;
4696
4697 // address = if index then offset_addr else R[n];
4698 if (index)
4699 address = offset_addr;
4700 else
4701 address = base_address;
4702
4703 uint32_t data;
4704 // if t == 15 then // Only possible for encoding A1
4705 if (t == 15)
4706 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004707 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004708 else
4709 // data = R[t];
4710 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4711
4712 if (!success)
4713 return false;
4714
4715 EmulateInstruction::Context context;
4716 context.type = eContextRegisterStore;
4717
4718 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4719 if (UnalignedSupport ()
4720 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4721 || CurrentInstrSet() == eModeARM)
4722 {
4723 // MemU[address,4] = data;
4724
4725 Register base_reg;
4726 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4727
4728 Register data_reg;
4729 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4730
4731 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004732 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004733 return false;
4734
4735 }
4736 else
4737 // MemU[address,4] = bits(32) UNKNOWN;
4738 WriteBits32UnknownToMemory (address);
4739
4740 // if wback then R[n] = offset_addr;
4741 if (wback)
4742 {
4743 context.type = eContextRegisterLoad;
4744 context.SetAddress (offset_addr);
4745 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4746 return false;
4747 }
4748
4749 }
4750 return true;
4751}
Caroline Tice73a29de2011-02-16 20:22:22 +00004752
4753bool
4754EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4755{
4756#if 0
4757 if ConditionPassed() then
4758 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4759 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4760 address = if index then offset_addr else R[n];
4761 MemU[address,1] = R[t]<7:0>;
4762 if wback then R[n] = offset_addr;
4763#endif
4764
4765
4766 bool success = false;
4767 const uint32_t opcode = OpcodeAsUnsigned (&success);
4768 if (!success)
4769 return false;
4770
4771 if (ConditionPassed ())
4772 {
4773 uint32_t t;
4774 uint32_t n;
4775 uint32_t imm32;
4776 bool index;
4777 bool add;
4778 bool wback;
4779 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4780 switch (encoding)
4781 {
4782 case eEncodingT1:
4783 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4784 t = Bits32 (opcode, 2, 0);
4785 n = Bits32 (opcode, 5, 3);
4786 imm32 = Bits32 (opcode, 10, 6);
4787
4788 // index = TRUE; add = TRUE; wback = FALSE;
4789 index = true;
4790 add = true;
4791 wback = false;
4792 break;
4793
4794 case eEncodingT2:
4795 // if Rn == ’1111’ then UNDEFINED;
4796 if (Bits32 (opcode, 19, 16) == 15)
4797 return false;
4798
4799 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4800 t = Bits32 (opcode, 15, 12);
4801 n = Bits32 (opcode, 19, 16);
4802 imm32 = Bits32 (opcode, 11, 0);
4803
4804 // index = TRUE; add = TRUE; wback = FALSE;
4805 index = true;
4806 add = true;
4807 wback = false;
4808
4809 // if BadReg(t) then UNPREDICTABLE;
4810 if (BadReg (t))
4811 return false;
4812 break;
4813
4814 case eEncodingT3:
4815 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4816 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4817 if (Bits32 (opcode, 19, 16) == 15)
4818 return false;
4819
4820 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4821 t = Bits32 (opcode, 15, 12);
4822 n = Bits32 (opcode, 19, 16);
4823 imm32 = Bits32 (opcode, 7, 0);
4824
4825 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4826 index = BitIsSet (opcode, 10);
4827 add = BitIsSet (opcode, 9);
4828 wback = BitIsSet (opcode, 8);
4829
4830 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4831 if ((BadReg (t)) || (wback && (n == t)))
4832 return false;
4833 break;
4834
4835 default:
4836 return false;
4837 }
4838
4839 addr_t offset_addr;
4840 addr_t address;
4841 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4842 if (!success)
4843 return false;
4844
4845 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4846 if (add)
4847 offset_addr = base_address + imm32;
4848 else
4849 offset_addr = base_address - imm32;
4850
4851 // address = if index then offset_addr else R[n];
4852 if (index)
4853 address = offset_addr;
4854 else
4855 address = base_address;
4856
Caroline Ticecc96eb52011-02-17 19:20:40 +00004857 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004858 Register base_reg;
4859 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4860
4861 Register data_reg;
4862 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4863
4864 EmulateInstruction::Context context;
4865 context.type = eContextRegisterStore;
4866 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4867
4868 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4869 if (!success)
4870 return false;
4871
4872 data = Bits32 (data, 7, 0);
4873
Caroline Ticecc96eb52011-02-17 19:20:40 +00004874 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004875 return false;
4876
4877 // if wback then R[n] = offset_addr;
4878 if (wback)
4879 {
4880 context.type = eContextRegisterLoad;
4881 context.SetAddress (offset_addr);
4882 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4883 return false;
4884 }
4885
4886 }
4887
4888 return true;
4889}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004890
4891// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4892// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4893bool
4894EmulateInstructionARM::EmulateSTRHRegister (ARMEncoding encoding)
4895{
4896#if 0
4897 if ConditionPassed() then
4898 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4899 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4900 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4901 address = if index then offset_addr else R[n];
4902 if UnalignedSupport() || address<0> == ’0’ then
4903 MemU[address,2] = R[t]<15:0>;
4904 else // Can only occur before ARMv7
4905 MemU[address,2] = bits(16) UNKNOWN;
4906 if wback then R[n] = offset_addr;
4907#endif
4908
4909 bool success = false;
4910 const uint32_t opcode = OpcodeAsUnsigned (&success);
4911 if (!success)
4912 return false;
4913
4914 if (ConditionPassed ())
4915 {
4916 uint32_t t;
4917 uint32_t n;
4918 uint32_t m;
4919 bool index;
4920 bool add;
4921 bool wback;
4922 ARM_ShifterType shift_t;
4923 uint32_t shift_n;
4924
4925 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4926 switch (encoding)
4927 {
4928 case eEncodingT1:
4929 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4930 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4931 t = Bits32 (opcode, 2, 0);
4932 n = Bits32 (opcode, 5, 3);
4933 m = Bits32 (opcode, 8, 6);
4934
4935 // index = TRUE; add = TRUE; wback = FALSE;
4936 index = true;
4937 add = true;
4938 wback = false;
4939
4940 // (shift_t, shift_n) = (SRType_LSL, 0);
4941 shift_t = SRType_LSL;
4942 shift_n = 0;
4943
4944 break;
4945
4946 case eEncodingT2:
4947 // if Rn == ’1111’ then UNDEFINED;
4948 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4949 t = Bits32 (opcode, 15, 12);
4950 n = Bits32 (opcode, 19, 16);
4951 m = Bits32 (opcode, 3, 0);
4952 if (n == 15)
4953 return false;
4954
4955 // index = TRUE; add = TRUE; wback = FALSE;
4956 index = true;
4957 add = true;
4958 wback = false;
4959
4960 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4961 shift_t = SRType_LSL;
4962 shift_n = Bits32 (opcode, 5, 4);
4963
4964 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4965 if (BadReg (t) || BadReg (m))
4966 return false;
4967
4968 break;
4969
4970 case eEncodingA1:
4971 // if P == ’0’ && W == ’1’ then SEE STRHT;
4972 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4973 t = Bits32 (opcode, 15, 12);
4974 n = Bits32 (opcode, 19, 16);
4975 m = Bits32 (opcode, 3, 0);
4976
4977 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4978 index = BitIsSet (opcode, 24);
4979 add = BitIsSet (opcode, 23);
4980 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4981
4982 // (shift_t, shift_n) = (SRType_LSL, 0);
4983 shift_t = SRType_LSL;
4984 shift_n = 0;
4985
4986 // if t == 15 || m == 15 then UNPREDICTABLE;
4987 if ((t == 15) || (m == 15))
4988 return false;
4989
4990 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4991 if (wback && ((n == 15) || (n == t)))
4992 return false;
4993
4994 break;
4995
4996 default:
4997 return false;
4998 }
4999
5000 uint32_t Rm = ReadCoreReg (m, &success);
5001 if (!success)
5002 return false;
5003
5004 uint32_t Rn = ReadCoreReg (n, &success);
5005 if (!success)
5006 return false;
5007
5008 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5009 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5010
5011 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5012 addr_t offset_addr;
5013 if (add)
5014 offset_addr = Rn + offset;
5015 else
5016 offset_addr = Rn - offset;
5017
5018 // address = if index then offset_addr else R[n];
5019 addr_t address;
5020 if (index)
5021 address = offset_addr;
5022 else
5023 address = Rn;
5024
5025 EmulateInstruction::Context context;
5026 context.type = eContextRegisterStore;
5027 Register base_reg;
5028 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5029 Register offset_reg;
5030 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5031
5032 // if UnalignedSupport() || address<0> == ’0’ then
5033 if (UnalignedSupport() || BitIsClear (address, 0))
5034 {
5035 // MemU[address,2] = R[t]<15:0>;
5036 uint32_t Rt = ReadCoreReg (t, &success);
5037 if (!success)
5038 return false;
5039
5040 EmulateInstruction::Context context;
5041 context.type = eContextRegisterStore;
5042 Register base_reg;
5043 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5044 Register offset_reg;
5045 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5046 Register data_reg;
5047 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5048 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5049
5050 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5051 return false;
5052 }
5053 else // Can only occur before ARMv7
5054 {
5055 // MemU[address,2] = bits(16) UNKNOWN;
5056 }
5057
5058 // if wback then R[n] = offset_addr;
5059 if (wback)
5060 {
5061 context.type = eContextAdjustBaseRegister;
5062 context.SetAddress (offset_addr);
5063 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5064 return false;
5065 }
5066 }
5067
5068 return true;
5069}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005070
Johnny Chen157b9592011-02-18 21:13:05 +00005071// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5072// and writes the result to the destination register. It can optionally update the condition flags
5073// based on the result.
5074bool
5075EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
5076{
5077#if 0
5078 // ARM pseudo code...
5079 if ConditionPassed() then
5080 EncodingSpecificOperations();
5081 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5082 if d == 15 then // Can only occur for ARM encoding
5083 ALUWritePC(result); // setflags is always FALSE here
5084 else
5085 R[d] = result;
5086 if setflags then
5087 APSR.N = result<31>;
5088 APSR.Z = IsZeroBit(result);
5089 APSR.C = carry;
5090 APSR.V = overflow;
5091#endif
5092
5093 bool success = false;
5094 const uint32_t opcode = OpcodeAsUnsigned (&success);
5095 if (!success)
5096 return false;
5097
5098 if (ConditionPassed())
5099 {
5100 uint32_t Rd, Rn;
5101 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5102 bool setflags;
5103 switch (encoding)
5104 {
5105 case eEncodingT1:
5106 Rd = Bits32(opcode, 11, 8);
5107 Rn = Bits32(opcode, 19, 16);
5108 setflags = BitIsSet(opcode, 20);
5109 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5110 if (BadReg(Rd) || BadReg(Rn))
5111 return false;
5112 break;
5113 case eEncodingA1:
5114 Rd = Bits32(opcode, 15, 12);
5115 Rn = Bits32(opcode, 19, 16);
5116 setflags = BitIsSet(opcode, 20);
5117 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5118 // TODO: Emulate SUBS PC, LR and related instructions.
5119 if (Rd == 15 && setflags)
5120 return false;
5121 break;
5122 default:
5123 return false;
5124 }
5125
5126 // Read the first operand.
5127 int32_t val1 = ReadCoreReg(Rn, &success);
5128 if (!success)
5129 return false;
5130
5131 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5132
5133 EmulateInstruction::Context context;
5134 context.type = EmulateInstruction::eContextImmediate;
5135 context.SetNoArgs ();
5136
5137 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5138 return false;
5139 }
5140 return true;
5141}
5142
5143// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5144// register value, and writes the result to the destination register. It can optionally update the
5145// condition flags based on the result.
5146bool
5147EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
5148{
5149#if 0
5150 // ARM pseudo code...
5151 if ConditionPassed() then
5152 EncodingSpecificOperations();
5153 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5154 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5155 if d == 15 then // Can only occur for ARM encoding
5156 ALUWritePC(result); // setflags is always FALSE here
5157 else
5158 R[d] = result;
5159 if setflags then
5160 APSR.N = result<31>;
5161 APSR.Z = IsZeroBit(result);
5162 APSR.C = carry;
5163 APSR.V = overflow;
5164#endif
5165
5166 bool success = false;
5167 const uint32_t opcode = OpcodeAsUnsigned (&success);
5168 if (!success)
5169 return false;
5170
5171 if (ConditionPassed())
5172 {
5173 uint32_t Rd, Rn, Rm;
5174 ARM_ShifterType shift_t;
5175 uint32_t shift_n; // the shift applied to the value read from Rm
5176 bool setflags;
5177 switch (encoding)
5178 {
5179 case eEncodingT1:
5180 Rd = Rn = Bits32(opcode, 2, 0);
5181 Rm = Bits32(opcode, 5, 3);
5182 setflags = !InITBlock();
5183 shift_t = SRType_LSL;
5184 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005185 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005186 case eEncodingT2:
5187 Rd = Bits32(opcode, 11, 8);
5188 Rn = Bits32(opcode, 19, 16);
5189 Rm = Bits32(opcode, 3, 0);
5190 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005191 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005192 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5193 return false;
5194 break;
5195 case eEncodingA1:
5196 Rd = Bits32(opcode, 15, 12);
5197 Rn = Bits32(opcode, 19, 16);
5198 Rm = Bits32(opcode, 3, 0);
5199 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005200 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005201 // TODO: Emulate SUBS PC, LR and related instructions.
5202 if (Rd == 15 && setflags)
5203 return false;
5204 break;
5205 default:
5206 return false;
5207 }
5208
5209 // Read the first operand.
5210 int32_t val1 = ReadCoreReg(Rn, &success);
5211 if (!success)
5212 return false;
5213
5214 // Read the second operand.
5215 int32_t val2 = ReadCoreReg(Rm, &success);
5216 if (!success)
5217 return false;
5218
5219 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5220 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5221
5222 EmulateInstruction::Context context;
5223 context.type = EmulateInstruction::eContextImmediate;
5224 context.SetNoArgs ();
5225
5226 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5227 return false;
5228 }
5229 return true;
5230}
5231
Johnny Chena695f952011-02-23 21:24:25 +00005232// This instruction adds an immediate value to the PC value to form a PC-relative address,
5233// and writes the result to the destination register.
5234bool
5235EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
5236{
5237#if 0
5238 // ARM pseudo code...
5239 if ConditionPassed() then
5240 EncodingSpecificOperations();
5241 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5242 if d == 15 then // Can only occur for ARM encodings
5243 ALUWritePC(result);
5244 else
5245 R[d] = result;
5246#endif
5247
5248 bool success = false;
5249 const uint32_t opcode = OpcodeAsUnsigned (&success);
5250 if (!success)
5251 return false;
5252
5253 if (ConditionPassed())
5254 {
5255 uint32_t Rd;
5256 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5257 bool add;
5258 switch (encoding)
5259 {
5260 case eEncodingT1:
5261 Rd = Bits32(opcode, 10, 8);
5262 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5263 break;
5264 case eEncodingT2:
5265 case eEncodingT3:
5266 Rd = Bits32(opcode, 11, 8);
5267 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5268 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5269 if (BadReg(Rd))
5270 return false;
5271 break;
5272 case eEncodingA1:
5273 case eEncodingA2:
5274 Rd = Bits32(opcode, 15, 12);
5275 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5276 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5277 break;
5278 default:
5279 return false;
5280 }
5281
5282 // Read the PC value.
5283 uint32_t pc = ReadCoreReg(PC_REG, &success);
5284 if (!success)
5285 return false;
5286
5287 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5288
5289 EmulateInstruction::Context context;
5290 context.type = EmulateInstruction::eContextImmediate;
5291 context.SetNoArgs ();
5292
5293 if (!WriteCoreReg(context, result, Rd))
5294 return false;
5295 }
5296 return true;
5297}
5298
Johnny Chene97c0d52011-02-18 19:32:20 +00005299// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5300// to the destination register. It can optionally update the condition flags based on the result.
5301bool
5302EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5303{
5304#if 0
5305 // ARM pseudo code...
5306 if ConditionPassed() then
5307 EncodingSpecificOperations();
5308 result = R[n] AND imm32;
5309 if d == 15 then // Can only occur for ARM encoding
5310 ALUWritePC(result); // setflags is always FALSE here
5311 else
5312 R[d] = result;
5313 if setflags then
5314 APSR.N = result<31>;
5315 APSR.Z = IsZeroBit(result);
5316 APSR.C = carry;
5317 // APSR.V unchanged
5318#endif
5319
5320 bool success = false;
5321 const uint32_t opcode = OpcodeAsUnsigned (&success);
5322 if (!success)
5323 return false;
5324
5325 if (ConditionPassed())
5326 {
5327 uint32_t Rd, Rn;
5328 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5329 bool setflags;
5330 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5331 switch (encoding)
5332 {
5333 case eEncodingT1:
5334 Rd = Bits32(opcode, 11, 8);
5335 Rn = Bits32(opcode, 19, 16);
5336 setflags = BitIsSet(opcode, 20);
5337 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005338 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005339 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005340 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005341 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5342 return false;
5343 break;
5344 case eEncodingA1:
5345 Rd = Bits32(opcode, 15, 12);
5346 Rn = Bits32(opcode, 19, 16);
5347 setflags = BitIsSet(opcode, 20);
5348 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5349 // TODO: Emulate SUBS PC, LR and related instructions.
5350 if (Rd == 15 && setflags)
5351 return false;
5352 break;
5353 default:
5354 return false;
5355 }
5356
Johnny Chene97c0d52011-02-18 19:32:20 +00005357 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005358 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005359 if (!success)
5360 return false;
5361
5362 uint32_t result = val1 & imm32;
5363
5364 EmulateInstruction::Context context;
5365 context.type = EmulateInstruction::eContextImmediate;
5366 context.SetNoArgs ();
5367
5368 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5369 return false;
5370 }
5371 return true;
5372}
5373
5374// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5375// and writes the result to the destination register. It can optionally update the condition flags
5376// based on the result.
5377bool
5378EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5379{
5380#if 0
5381 // ARM pseudo code...
5382 if ConditionPassed() then
5383 EncodingSpecificOperations();
5384 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5385 result = R[n] AND shifted;
5386 if d == 15 then // Can only occur for ARM encoding
5387 ALUWritePC(result); // setflags is always FALSE here
5388 else
5389 R[d] = result;
5390 if setflags then
5391 APSR.N = result<31>;
5392 APSR.Z = IsZeroBit(result);
5393 APSR.C = carry;
5394 // APSR.V unchanged
5395#endif
5396
5397 bool success = false;
5398 const uint32_t opcode = OpcodeAsUnsigned (&success);
5399 if (!success)
5400 return false;
5401
5402 if (ConditionPassed())
5403 {
5404 uint32_t Rd, Rn, Rm;
5405 ARM_ShifterType shift_t;
5406 uint32_t shift_n; // the shift applied to the value read from Rm
5407 bool setflags;
5408 uint32_t carry;
5409 switch (encoding)
5410 {
5411 case eEncodingT1:
5412 Rd = Rn = Bits32(opcode, 2, 0);
5413 Rm = Bits32(opcode, 5, 3);
5414 setflags = !InITBlock();
5415 shift_t = SRType_LSL;
5416 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005417 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005418 case eEncodingT2:
5419 Rd = Bits32(opcode, 11, 8);
5420 Rn = Bits32(opcode, 19, 16);
5421 Rm = Bits32(opcode, 3, 0);
5422 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005423 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005424 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005425 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005426 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005427 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5428 return false;
5429 break;
5430 case eEncodingA1:
5431 Rd = Bits32(opcode, 15, 12);
5432 Rn = Bits32(opcode, 19, 16);
5433 Rm = Bits32(opcode, 3, 0);
5434 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005435 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005436 // TODO: Emulate SUBS PC, LR and related instructions.
5437 if (Rd == 15 && setflags)
5438 return false;
5439 break;
5440 default:
5441 return false;
5442 }
5443
Johnny Chene97c0d52011-02-18 19:32:20 +00005444 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005445 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005446 if (!success)
5447 return false;
5448
5449 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005450 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005451 if (!success)
5452 return false;
5453
5454 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5455 uint32_t result = val1 & shifted;
5456
5457 EmulateInstruction::Context context;
5458 context.type = EmulateInstruction::eContextImmediate;
5459 context.SetNoArgs ();
5460
5461 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5462 return false;
5463 }
5464 return true;
5465}
5466
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005467// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5468// immediate value, and writes the result to the destination register. It can optionally update the
5469// condition flags based on the result.
5470bool
5471EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5472{
5473#if 0
5474 // ARM pseudo code...
5475 if ConditionPassed() then
5476 EncodingSpecificOperations();
5477 result = R[n] AND NOT(imm32);
5478 if d == 15 then // Can only occur for ARM encoding
5479 ALUWritePC(result); // setflags is always FALSE here
5480 else
5481 R[d] = result;
5482 if setflags then
5483 APSR.N = result<31>;
5484 APSR.Z = IsZeroBit(result);
5485 APSR.C = carry;
5486 // APSR.V unchanged
5487#endif
5488
5489 bool success = false;
5490 const uint32_t opcode = OpcodeAsUnsigned (&success);
5491 if (!success)
5492 return false;
5493
5494 if (ConditionPassed())
5495 {
5496 uint32_t Rd, Rn;
5497 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5498 bool setflags;
5499 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5500 switch (encoding)
5501 {
5502 case eEncodingT1:
5503 Rd = Bits32(opcode, 11, 8);
5504 Rn = Bits32(opcode, 19, 16);
5505 setflags = BitIsSet(opcode, 20);
5506 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5507 if (BadReg(Rd) || BadReg(Rn))
5508 return false;
5509 break;
5510 case eEncodingA1:
5511 Rd = Bits32(opcode, 15, 12);
5512 Rn = Bits32(opcode, 19, 16);
5513 setflags = BitIsSet(opcode, 20);
5514 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5515 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5516 // TODO: Emulate SUBS PC, LR and related instructions.
5517 if (Rd == 15 && setflags)
5518 return false;
5519 break;
5520 default:
5521 return false;
5522 }
5523
5524 // Read the first operand.
5525 uint32_t val1 = ReadCoreReg(Rn, &success);
5526 if (!success)
5527 return false;
5528
5529 uint32_t result = val1 & ~imm32;
5530
5531 EmulateInstruction::Context context;
5532 context.type = EmulateInstruction::eContextImmediate;
5533 context.SetNoArgs ();
5534
5535 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5536 return false;
5537 }
5538 return true;
5539}
5540
5541// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5542// optionally-shifted register value, and writes the result to the destination register.
5543// It can optionally update the condition flags based on the result.
5544bool
5545EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5546{
5547#if 0
5548 // ARM pseudo code...
5549 if ConditionPassed() then
5550 EncodingSpecificOperations();
5551 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5552 result = R[n] AND NOT(shifted);
5553 if d == 15 then // Can only occur for ARM encoding
5554 ALUWritePC(result); // setflags is always FALSE here
5555 else
5556 R[d] = result;
5557 if setflags then
5558 APSR.N = result<31>;
5559 APSR.Z = IsZeroBit(result);
5560 APSR.C = carry;
5561 // APSR.V unchanged
5562#endif
5563
5564 bool success = false;
5565 const uint32_t opcode = OpcodeAsUnsigned (&success);
5566 if (!success)
5567 return false;
5568
5569 if (ConditionPassed())
5570 {
5571 uint32_t Rd, Rn, Rm;
5572 ARM_ShifterType shift_t;
5573 uint32_t shift_n; // the shift applied to the value read from Rm
5574 bool setflags;
5575 uint32_t carry;
5576 switch (encoding)
5577 {
5578 case eEncodingT1:
5579 Rd = Rn = Bits32(opcode, 2, 0);
5580 Rm = Bits32(opcode, 5, 3);
5581 setflags = !InITBlock();
5582 shift_t = SRType_LSL;
5583 shift_n = 0;
5584 break;
5585 case eEncodingT2:
5586 Rd = Bits32(opcode, 11, 8);
5587 Rn = Bits32(opcode, 19, 16);
5588 Rm = Bits32(opcode, 3, 0);
5589 setflags = BitIsSet(opcode, 20);
5590 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5591 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5592 return false;
5593 break;
5594 case eEncodingA1:
5595 Rd = Bits32(opcode, 15, 12);
5596 Rn = Bits32(opcode, 19, 16);
5597 Rm = Bits32(opcode, 3, 0);
5598 setflags = BitIsSet(opcode, 20);
5599 shift_n = DecodeImmShiftARM(opcode, shift_t);
5600 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5601 // TODO: Emulate SUBS PC, LR and related instructions.
5602 if (Rd == 15 && setflags)
5603 return false;
5604 break;
5605 default:
5606 return false;
5607 }
5608
5609 // Read the first operand.
5610 uint32_t val1 = ReadCoreReg(Rn, &success);
5611 if (!success)
5612 return false;
5613
5614 // Read the second operand.
5615 uint32_t val2 = ReadCoreReg(Rm, &success);
5616 if (!success)
5617 return false;
5618
5619 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5620 uint32_t result = val1 & ~shifted;
5621
5622 EmulateInstruction::Context context;
5623 context.type = EmulateInstruction::eContextImmediate;
5624 context.SetNoArgs ();
5625
5626 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5627 return false;
5628 }
5629 return true;
5630}
5631
Caroline Tice4d729c52011-02-18 00:55:53 +00005632// 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 +00005633// 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 +00005634bool
5635EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5636{
5637#if 0
5638 if ConditionPassed() then
5639 EncodingSpecificOperations();
5640 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5641 address = if index then offset_addr else R[n];
5642 data = MemU[address,4];
5643 if wback then R[n] = offset_addr;
5644 if t == 15 then
5645 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5646 elsif UnalignedSupport() || address<1:0> = ’00’ then
5647 R[t] = data;
5648 else // Can only apply before ARMv7
5649 R[t] = ROR(data, 8*UInt(address<1:0>));
5650#endif
5651
5652 bool success = false;
5653 const uint32_t opcode = OpcodeAsUnsigned (&success);
5654 if (!success)
5655 return false;
5656
5657 if (ConditionPassed ())
5658 {
5659 const uint32_t addr_byte_size = GetAddressByteSize();
5660
5661 uint32_t t;
5662 uint32_t n;
5663 uint32_t imm32;
5664 bool index;
5665 bool add;
5666 bool wback;
5667
5668 switch (encoding)
5669 {
5670 case eEncodingA1:
5671 // if Rn == ’1111’ then SEE LDR (literal);
5672 // if P == ’0’ && W == ’1’ then SEE LDRT;
5673 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5674 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5675 t = Bits32 (opcode, 15, 12);
5676 n = Bits32 (opcode, 19, 16);
5677 imm32 = Bits32 (opcode, 11, 0);
5678
5679 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5680 index = BitIsSet (opcode, 24);
5681 add = BitIsSet (opcode, 23);
5682 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5683
5684 // if wback && n == t then UNPREDICTABLE;
5685 if (wback && (n == t))
5686 return false;
5687
5688 break;
5689
5690 default:
5691 return false;
5692 }
5693
5694 addr_t address;
5695 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005696 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005697 if (!success)
5698 return false;
5699
5700 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5701 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005702 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005703 else
5704 offset_addr = base_address - imm32;
5705
5706 // address = if index then offset_addr else R[n];
5707 if (index)
5708 address = offset_addr;
5709 else
5710 address = base_address;
5711
5712 // data = MemU[address,4];
5713
5714 Register base_reg;
5715 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5716
5717 EmulateInstruction::Context context;
5718 context.type = eContextRegisterLoad;
5719 context.SetRegisterPlusOffset (base_reg, address - base_address);
5720
5721 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5722 if (!success)
5723 return false;
5724
5725 // if wback then R[n] = offset_addr;
5726 if (wback)
5727 {
5728 context.type = eContextAdjustBaseRegister;
5729 context.SetAddress (offset_addr);
5730 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5731 return false;
5732 }
5733
5734 // if t == 15 then
5735 if (t == 15)
5736 {
5737 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5738 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5739 {
5740 // LoadWritePC (data);
5741 context.type = eContextRegisterLoad;
5742 context.SetRegisterPlusOffset (base_reg, address - base_address);
5743 LoadWritePC (context, data);
5744 }
5745 else
5746 return false;
5747 }
5748 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5749 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5750 {
5751 // R[t] = data;
5752 context.type = eContextRegisterLoad;
5753 context.SetRegisterPlusOffset (base_reg, address - base_address);
5754 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5755 return false;
5756 }
5757 // else // Can only apply before ARMv7
5758 else
5759 {
5760 // R[t] = ROR(data, 8*UInt(address<1:0>));
5761 data = ROR (data, Bits32 (address, 1, 0));
5762 context.type = eContextRegisterLoad;
5763 context.SetImmediate (data);
5764 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5765 return false;
5766 }
5767
5768 }
5769 return true;
5770}
5771
Caroline Ticefe479112011-02-18 18:52:37 +00005772// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5773// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5774bool
5775EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5776{
5777#if 0
5778 if ConditionPassed() then
5779 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5780 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5781 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5782 address = if index then offset_addr else R[n];
5783 data = MemU[address,4];
5784 if wback then R[n] = offset_addr;
5785 if t == 15 then
5786 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5787 elsif UnalignedSupport() || address<1:0> = ’00’ then
5788 R[t] = data;
5789 else // Can only apply before ARMv7
5790 if CurrentInstrSet() == InstrSet_ARM then
5791 R[t] = ROR(data, 8*UInt(address<1:0>));
5792 else
5793 R[t] = bits(32) UNKNOWN;
5794#endif
5795
5796 bool success = false;
5797 const uint32_t opcode = OpcodeAsUnsigned (&success);
5798 if (!success)
5799 return false;
5800
5801 if (ConditionPassed ())
5802 {
5803 const uint32_t addr_byte_size = GetAddressByteSize();
5804
5805 uint32_t t;
5806 uint32_t n;
5807 uint32_t m;
5808 bool index;
5809 bool add;
5810 bool wback;
5811 ARM_ShifterType shift_t;
5812 uint32_t shift_n;
5813
5814 switch (encoding)
5815 {
5816 case eEncodingT1:
5817 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5818 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5819 t = Bits32 (opcode, 2, 0);
5820 n = Bits32 (opcode, 5, 3);
5821 m = Bits32 (opcode, 8, 6);
5822
5823 // index = TRUE; add = TRUE; wback = FALSE;
5824 index = true;
5825 add = true;
5826 wback = false;
5827
5828 // (shift_t, shift_n) = (SRType_LSL, 0);
5829 shift_t = SRType_LSL;
5830 shift_n = 0;
5831
5832 break;
5833
5834 case eEncodingT2:
5835 // if Rn == ’1111’ then SEE LDR (literal);
5836 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5837 t = Bits32 (opcode, 15, 12);
5838 n = Bits32 (opcode, 19, 16);
5839 m = Bits32 (opcode, 3, 0);
5840
5841 // index = TRUE; add = TRUE; wback = FALSE;
5842 index = true;
5843 add = true;
5844 wback = false;
5845
5846 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5847 shift_t = SRType_LSL;
5848 shift_n = Bits32 (opcode, 5, 4);
5849
5850 // if BadReg(m) then UNPREDICTABLE;
5851 if (BadReg (m))
5852 return false;
5853
5854 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5855 if ((t == 15) && InITBlock() && !LastInITBlock())
5856 return false;
5857
5858 break;
5859
5860 case eEncodingA1:
5861 {
5862 // if P == ’0’ && W == ’1’ then SEE LDRT;
5863 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5864 t = Bits32 (opcode, 15, 12);
5865 n = Bits32 (opcode, 19, 16);
5866 m = Bits32 (opcode, 3, 0);
5867
5868 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5869 index = BitIsSet (opcode, 24);
5870 add = BitIsSet (opcode, 23);
5871 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5872
5873 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5874 uint32_t type = Bits32 (opcode, 6, 5);
5875 uint32_t imm5 = Bits32 (opcode, 11, 7);
5876 shift_n = DecodeImmShift (type, imm5, shift_t);
5877
5878 // if m == 15 then UNPREDICTABLE;
5879 if (m == 15)
5880 return false;
5881
5882 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5883 if (wback && ((n == 15) || (n == t)))
5884 return false;
5885 }
5886 break;
5887
5888
5889 default:
5890 return false;
5891 }
5892
5893 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5894 if (!success)
5895 return false;
5896
5897 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5898 if (!success)
5899 return false;
5900
5901 addr_t offset_addr;
5902 addr_t address;
5903
5904 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chen90e607b2011-02-23 00:07:09 +00005905 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005906
5907 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5908 if (add)
5909 offset_addr = Rn + offset;
5910 else
5911 offset_addr = Rn - offset;
5912
5913 // address = if index then offset_addr else R[n];
5914 if (index)
5915 address = offset_addr;
5916 else
5917 address = Rn;
5918
5919 // data = MemU[address,4];
5920 Register base_reg;
5921 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5922
5923 EmulateInstruction::Context context;
5924 context.type = eContextRegisterLoad;
5925 context.SetRegisterPlusOffset (base_reg, address - Rn);
5926
5927 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5928 if (!success)
5929 return false;
5930
5931 // if wback then R[n] = offset_addr;
5932 if (wback)
5933 {
5934 context.type = eContextAdjustBaseRegister;
5935 context.SetAddress (offset_addr);
5936 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5937 return false;
5938 }
5939
5940 // if t == 15 then
5941 if (t == 15)
5942 {
5943 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5944 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5945 {
5946 context.type = eContextRegisterLoad;
5947 context.SetRegisterPlusOffset (base_reg, address - Rn);
5948 LoadWritePC (context, data);
5949 }
5950 else
5951 return false;
5952 }
5953 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5954 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5955 {
5956 // R[t] = data;
5957 context.type = eContextRegisterLoad;
5958 context.SetRegisterPlusOffset (base_reg, address - Rn);
5959 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5960 return false;
5961 }
5962 else // Can only apply before ARMv7
5963 {
5964 // if CurrentInstrSet() == InstrSet_ARM then
5965 if (CurrentInstrSet () == eModeARM)
5966 {
5967 // R[t] = ROR(data, 8*UInt(address<1:0>));
5968 data = ROR (data, Bits32 (address, 1, 0));
5969 context.type = eContextRegisterLoad;
5970 context.SetImmediate (data);
5971 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5972 return false;
5973 }
5974 else
5975 {
5976 // R[t] = bits(32) UNKNOWN;
5977 WriteBits32Unknown (t);
5978 }
5979 }
5980 }
5981 return true;
5982}
Caroline Tice21b604b2011-02-18 21:06:04 +00005983
5984// LDRB (immediate, Thumb)
5985bool
5986EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5987{
5988#if 0
5989 if ConditionPassed() then
5990 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5991 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5992 address = if index then offset_addr else R[n];
5993 R[t] = ZeroExtend(MemU[address,1], 32);
5994 if wback then R[n] = offset_addr;
5995#endif
5996
5997 bool success = false;
5998 const uint32_t opcode = OpcodeAsUnsigned (&success);
5999 if (!success)
6000 return false;
6001
6002 if (ConditionPassed ())
6003 {
6004 uint32_t t;
6005 uint32_t n;
6006 uint32_t imm32;
6007 bool index;
6008 bool add;
6009 bool wback;
6010
6011 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6012 switch (encoding)
6013 {
6014 case eEncodingT1:
6015 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6016 t = Bits32 (opcode, 2, 0);
6017 n = Bits32 (opcode, 5, 3);
6018 imm32 = Bits32 (opcode, 10, 6);
6019
6020 // index = TRUE; add = TRUE; wback = FALSE;
6021 index = true;
6022 add = true;
6023 wback= false;
6024
6025 break;
6026
6027 case eEncodingT2:
6028 // if Rt == ’1111’ then SEE PLD;
6029 // if Rn == ’1111’ then SEE LDRB (literal);
6030 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6031 t = Bits32 (opcode, 15, 12);
6032 n = Bits32 (opcode, 19, 16);
6033 imm32 = Bits32 (opcode, 11, 0);
6034
6035 // index = TRUE; add = TRUE; wback = FALSE;
6036 index = true;
6037 add = true;
6038 wback = false;
6039
6040 // if t == 13 then UNPREDICTABLE;
6041 if (t == 13)
6042 return false;
6043
6044 break;
6045
6046 case eEncodingT3:
6047 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
6048 // if Rn == ’1111’ then SEE LDRB (literal);
6049 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
6050 // if P == ’0’ && W == ’0’ then UNDEFINED;
6051 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6052 return false;
6053
6054 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6055 t = Bits32 (opcode, 15, 12);
6056 n = Bits32 (opcode, 19, 16);
6057 imm32 = Bits32 (opcode, 7, 0);
6058
6059 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6060 index = BitIsSet (opcode, 10);
6061 add = BitIsSet (opcode, 9);
6062 wback = BitIsSet (opcode, 8);
6063
6064 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6065 if (BadReg (t) || (wback && (n == t)))
6066 return false;
6067
6068 break;
6069
6070 default:
6071 return false;
6072 }
6073
6074 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6075 if (!success)
6076 return false;
6077
6078 addr_t address;
6079 addr_t offset_addr;
6080
6081 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6082 if (add)
6083 offset_addr = Rn + imm32;
6084 else
6085 offset_addr = Rn - imm32;
6086
6087 // address = if index then offset_addr else R[n];
6088 if (index)
6089 address = offset_addr;
6090 else
6091 address = Rn;
6092
6093 // R[t] = ZeroExtend(MemU[address,1], 32);
6094 Register base_reg;
6095 Register data_reg;
6096 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6097 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6098
6099 EmulateInstruction::Context context;
6100 context.type = eContextRegisterLoad;
6101 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6102
6103 uint64_t data = MemURead (context, address, 1, 0, &success);
6104 if (!success)
6105 return false;
6106
6107 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6108 return false;
6109
6110 // if wback then R[n] = offset_addr;
6111 if (wback)
6112 {
6113 context.type = eContextAdjustBaseRegister;
6114 context.SetAddress (offset_addr);
6115 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6116 return false;
6117 }
6118 }
6119 return true;
6120}
Caroline Ticef55261f2011-02-18 22:24:22 +00006121
6122// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6123// zero-extends it to form a 32-bit word and writes it to a register.
6124bool
6125EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
6126{
6127#if 0
6128 if ConditionPassed() then
6129 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6130 base = Align(PC,4);
6131 address = if add then (base + imm32) else (base - imm32);
6132 R[t] = ZeroExtend(MemU[address,1], 32);
6133#endif
6134
6135 bool success = false;
6136 const uint32_t opcode = OpcodeAsUnsigned (&success);
6137 if (!success)
6138 return false;
6139
6140 if (ConditionPassed ())
6141 {
6142 uint32_t t;
6143 uint32_t imm32;
6144 bool add;
6145 switch (encoding)
6146 {
6147 case eEncodingT1:
6148 // if Rt == ’1111’ then SEE PLD;
6149 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6150 t = Bits32 (opcode, 15, 12);
6151 imm32 = Bits32 (opcode, 11, 0);
6152 add = BitIsSet (opcode, 23);
6153
6154 // if t == 13 then UNPREDICTABLE;
6155 if (t == 13)
6156 return false;
6157
6158 break;
6159
6160 case eEncodingA1:
6161 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6162 t = Bits32 (opcode, 15, 12);
6163 imm32 = Bits32 (opcode, 11, 0);
6164 add = BitIsSet (opcode, 23);
6165
6166 // if t == 15 then UNPREDICTABLE;
6167 if (t == 15)
6168 return false;
6169 break;
6170
6171 default:
6172 return false;
6173 }
6174
6175 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006176 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006177 if (!success)
6178 return false;
6179
6180 uint32_t base = AlignPC (pc_val);
6181
6182 addr_t address;
6183 // address = if add then (base + imm32) else (base - imm32);
6184 if (add)
6185 address = base + imm32;
6186 else
6187 address = base - imm32;
6188
6189 // R[t] = ZeroExtend(MemU[address,1], 32);
6190 EmulateInstruction::Context context;
6191 context.type = eContextRelativeBranchImmediate;
6192 context.SetImmediate (address - base);
6193
6194 uint64_t data = MemURead (context, address, 1, 0, &success);
6195 if (!success)
6196 return false;
6197
6198 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6199 return false;
6200 }
6201 return true;
6202}
Caroline Tice30fec122011-02-18 23:52:21 +00006203
6204// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6205// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6206// optionally be shifted.
6207bool
6208EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
6209{
6210#if 0
6211 if ConditionPassed() then
6212 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6213 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6214 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6215 address = if index then offset_addr else R[n];
6216 R[t] = ZeroExtend(MemU[address,1],32);
6217 if wback then R[n] = offset_addr;
6218#endif
6219
6220 bool success = false;
6221 const uint32_t opcode = OpcodeAsUnsigned (&success);
6222 if (!success)
6223 return false;
6224
6225 if (ConditionPassed ())
6226 {
6227 uint32_t t;
6228 uint32_t n;
6229 uint32_t m;
6230 bool index;
6231 bool add;
6232 bool wback;
6233 ARM_ShifterType shift_t;
6234 uint32_t shift_n;
6235
6236 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6237 switch (encoding)
6238 {
6239 case eEncodingT1:
6240 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6241 t = Bits32 (opcode, 2, 0);
6242 n = Bits32 (opcode, 5, 3);
6243 m = Bits32 (opcode, 8, 6);
6244
6245 // index = TRUE; add = TRUE; wback = FALSE;
6246 index = true;
6247 add = true;
6248 wback = false;
6249
6250 // (shift_t, shift_n) = (SRType_LSL, 0);
6251 shift_t = SRType_LSL;
6252 shift_n = 0;
6253 break;
6254
6255 case eEncodingT2:
6256 // if Rt == ’1111’ then SEE PLD;
6257 // if Rn == ’1111’ then SEE LDRB (literal);
6258 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6259 t = Bits32 (opcode, 15, 12);
6260 n = Bits32 (opcode, 19, 16);
6261 m = Bits32 (opcode, 3, 0);
6262
6263 // index = TRUE; add = TRUE; wback = FALSE;
6264 index = true;
6265 add = true;
6266 wback = false;
6267
6268 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6269 shift_t = SRType_LSL;
6270 shift_n = Bits32 (opcode, 5, 4);
6271
6272 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6273 if ((t == 13) || BadReg (m))
6274 return false;
6275 break;
6276
6277 case eEncodingA1:
6278 {
6279 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6280 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6281 t = Bits32 (opcode, 15, 12);
6282 n = Bits32 (opcode, 19, 16);
6283 m = Bits32 (opcode, 3, 0);
6284
6285 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6286 index = BitIsSet (opcode, 24);
6287 add = BitIsSet (opcode, 23);
6288 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6289
6290 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6291 uint32_t type = Bits32 (opcode, 6, 5);
6292 uint32_t imm5 = Bits32 (opcode, 11, 7);
6293 shift_n = DecodeImmShift (type, imm5, shift_t);
6294
6295 // if t == 15 || m == 15 then UNPREDICTABLE;
6296 if ((t == 15) || (m == 15))
6297 return false;
6298
6299 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6300 if (wback && ((n == 15) || (n == t)))
6301 return false;
6302 }
6303 break;
6304
6305 default:
6306 return false;
6307 }
6308
6309 addr_t offset_addr;
6310 addr_t address;
6311
6312 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6313 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6314 if (!success)
6315 return false;
6316
6317 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6318
6319 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6320 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6321 if (!success)
6322 return false;
6323
6324 if (add)
6325 offset_addr = Rn + offset;
6326 else
6327 offset_addr = Rn - offset;
6328
6329 // address = if index then offset_addr else R[n];
6330 if (index)
6331 address = offset_addr;
6332 else
6333 address = Rn;
6334
6335 // R[t] = ZeroExtend(MemU[address,1],32);
6336 Register base_reg;
6337 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6338
6339 EmulateInstruction::Context context;
6340 context.type = eContextRegisterLoad;
6341 context.SetRegisterPlusOffset (base_reg, address - Rn);
6342
6343 uint64_t data = MemURead (context, address, 1, 0, &success);
6344 if (!success)
6345 return false;
6346
6347 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6348 return false;
6349
6350 // if wback then R[n] = offset_addr;
6351 if (wback)
6352 {
6353 context.type = eContextAdjustBaseRegister;
6354 context.SetAddress (offset_addr);
6355 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6356 return false;
6357 }
6358 }
6359 return true;
6360}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006361
6362// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6363// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6364// post-indexed, or pre-indexed addressing.
6365bool
6366EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6367{
6368#if 0
6369 if ConditionPassed() then
6370 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6371 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6372 address = if index then offset_addr else R[n];
6373 data = MemU[address,2];
6374 if wback then R[n] = offset_addr;
6375 if UnalignedSupport() || address<0> = ’0’ then
6376 R[t] = ZeroExtend(data, 32);
6377 else // Can only apply before ARMv7
6378 R[t] = bits(32) UNKNOWN;
6379#endif
6380
6381
6382 bool success = false;
6383 const uint32_t opcode = OpcodeAsUnsigned (&success);
6384 if (!success)
6385 return false;
6386
6387 if (ConditionPassed())
6388 {
6389 uint32_t t;
6390 uint32_t n;
6391 uint32_t imm32;
6392 bool index;
6393 bool add;
6394 bool wback;
6395
6396 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6397 switch (encoding)
6398 {
6399 case eEncodingT1:
6400 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6401 t = Bits32 (opcode, 2, 0);
6402 n = Bits32 (opcode, 5, 3);
6403 imm32 = Bits32 (opcode, 10, 6) << 1;
6404
6405 // index = TRUE; add = TRUE; wback = FALSE;
6406 index = true;
6407 add = true;
6408 wback = false;
6409
6410 break;
6411
6412 case eEncodingT2:
6413 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6414 // if Rn == ’1111’ then SEE LDRH (literal);
6415 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6416 t = Bits32 (opcode, 15, 12);
6417 n = Bits32 (opcode, 19, 16);
6418 imm32 = Bits32 (opcode, 11, 0);
6419
6420 // index = TRUE; add = TRUE; wback = FALSE;
6421 index = true;
6422 add = true;
6423 wback = false;
6424
6425 // if t == 13 then UNPREDICTABLE;
6426 if (t == 13)
6427 return false;
6428 break;
6429
6430 case eEncodingT3:
6431 // if Rn == ’1111’ then SEE LDRH (literal);
6432 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6433 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6434 // if P == ’0’ && W == ’0’ then UNDEFINED;
6435 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6436 return false;
6437
6438 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6439 t = Bits32 (opcode, 15, 12);
6440 n = Bits32 (opcode, 19, 16);
6441 imm32 = Bits32 (opcode, 7, 0);
6442
6443 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6444 index = BitIsSet (opcode, 10);
6445 add = BitIsSet (opcode, 9);
6446 wback = BitIsSet (opcode, 8);
6447
6448 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6449 if (BadReg (t) || (wback && (n == t)))
6450 return false;
6451 break;
6452
6453 default:
6454 return false;
6455 }
6456
6457 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6458 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6459 if (!success)
6460 return false;
6461
6462 addr_t offset_addr;
6463 addr_t address;
6464
6465 if (add)
6466 offset_addr = Rn + imm32;
6467 else
6468 offset_addr = Rn - imm32;
6469
6470 // address = if index then offset_addr else R[n];
6471 if (index)
6472 address = offset_addr;
6473 else
6474 address = Rn;
6475
6476 // data = MemU[address,2];
6477 Register base_reg;
6478 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6479
6480 EmulateInstruction::Context context;
6481 context.type = eContextRegisterLoad;
6482 context.SetRegisterPlusOffset (base_reg, address - Rn);
6483
6484 uint64_t data = MemURead (context, address, 2, 0, &success);
6485 if (!success)
6486 return false;
6487
6488 // if wback then R[n] = offset_addr;
6489 if (wback)
6490 {
6491 context.type = eContextAdjustBaseRegister;
6492 context.SetAddress (offset_addr);
6493 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6494 return false;
6495 }
6496
6497 // if UnalignedSupport() || address<0> = ’0’ then
6498 if (UnalignedSupport () || BitIsClear (address, 0))
6499 {
6500 // R[t] = ZeroExtend(data, 32);
6501 context.type = eContextRegisterLoad;
6502 context.SetRegisterPlusOffset (base_reg, address - Rn);
6503 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6504 return false;
6505 }
6506 else // Can only apply before ARMv7
6507 {
6508 // R[t] = bits(32) UNKNOWN;
6509 WriteBits32Unknown (t);
6510 }
6511 }
6512 return true;
6513}
Caroline Ticefe479112011-02-18 18:52:37 +00006514
Caroline Tice952b5382011-02-28 23:15:24 +00006515// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6516// zero-extends it to form a 32-bit word, and writes it to a register.
6517bool
6518EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6519{
6520#if 0
6521 if ConditionPassed() then
6522 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6523 base = Align(PC,4);
6524 address = if add then (base + imm32) else (base - imm32);
6525 data = MemU[address,2];
6526 if UnalignedSupport() || address<0> = ’0’ then
6527 R[t] = ZeroExtend(data, 32);
6528 else // Can only apply before ARMv7
6529 R[t] = bits(32) UNKNOWN;
6530#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006531
Caroline Tice952b5382011-02-28 23:15:24 +00006532 bool success = false;
6533 const uint32_t opcode = OpcodeAsUnsigned (&success);
6534 if (!success)
6535 return false;
6536
6537 if (ConditionPassed())
6538 {
6539 uint32_t t;
6540 uint32_t imm32;
6541 bool add;
6542
6543 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6544 switch (encoding)
6545 {
6546 case eEncodingT1:
6547 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6548 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6549 t = Bits32 (opcode, 15, 12);
6550 imm32 = Bits32 (opcode, 11, 0);
6551 add = BitIsSet (opcode, 23);
6552
6553 // if t == 13 then UNPREDICTABLE;
6554 if (t == 13)
6555 return false;
6556
6557 break;
6558
6559 case eEncodingA1:
6560 {
6561 uint32_t imm4H = Bits32 (opcode, 11, 8);
6562 uint32_t imm4L = Bits32 (opcode, 3, 0);
6563
6564 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6565 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006566 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006567 add = BitIsSet (opcode, 23);
6568
6569 // if t == 15 then UNPREDICTABLE;
6570 if (t == 15)
6571 return false;
6572 break;
6573 }
6574
6575 default:
6576 return false;
6577 }
6578
6579 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006580 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006581 if (!success)
6582 return false;
6583
6584 addr_t base = AlignPC (pc_value);
6585 addr_t address;
6586
6587 // address = if add then (base + imm32) else (base - imm32);
6588 if (add)
6589 address = base + imm32;
6590 else
6591 address = base - imm32;
6592
6593 // data = MemU[address,2];
6594 Register base_reg;
6595 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6596
6597 EmulateInstruction::Context context;
6598 context.type = eContextRegisterLoad;
6599 context.SetRegisterPlusOffset (base_reg, address - base);
6600
6601 uint64_t data = MemURead (context, address, 2, 0, &success);
6602 if (!success)
6603 return false;
6604
6605
6606 // if UnalignedSupport() || address<0> = ’0’ then
6607 if (UnalignedSupport () || BitIsClear (address, 0))
6608 {
6609 // R[t] = ZeroExtend(data, 32);
6610 context.type = eContextRegisterLoad;
6611 context.SetRegisterPlusOffset (base_reg, address - base);
6612 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6613 return false;
6614
6615 }
6616 else // Can only apply before ARMv7
6617 {
6618 // R[t] = bits(32) UNKNOWN;
6619 WriteBits32Unknown (t);
6620 }
6621 }
6622 return true;
6623}
6624
Caroline Tice0e6bc952011-03-01 18:00:42 +00006625// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6626// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6627// be shifted left by 0, 1, 2, or 3 bits.
6628bool
6629EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6630{
6631#if 0
6632 if ConditionPassed() then
6633 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6634 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6635 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6636 address = if index then offset_addr else R[n];
6637 data = MemU[address,2];
6638 if wback then R[n] = offset_addr;
6639 if UnalignedSupport() || address<0> = ’0’ then
6640 R[t] = ZeroExtend(data, 32);
6641 else // Can only apply before ARMv7
6642 R[t] = bits(32) UNKNOWN;
6643#endif
6644
6645 bool success = false;
6646 const uint32_t opcode = OpcodeAsUnsigned (&success);
6647 if (!success)
6648 return false;
6649
6650 if (ConditionPassed())
6651 {
6652 uint32_t t;
6653 uint32_t n;
6654 uint32_t m;
6655 bool index;
6656 bool add;
6657 bool wback;
6658 ARM_ShifterType shift_t;
6659 uint32_t shift_n;
6660
6661 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6662 switch (encoding)
6663 {
6664 case eEncodingT1:
6665 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6666 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6667 t = Bits32 (opcode, 2, 0);
6668 n = Bits32 (opcode, 5, 3);
6669 m = Bits32 (opcode, 8, 6);
6670
6671 // index = TRUE; add = TRUE; wback = FALSE;
6672 index = true;
6673 add = true;
6674 wback = false;
6675
6676 // (shift_t, shift_n) = (SRType_LSL, 0);
6677 shift_t = SRType_LSL;
6678 shift_n = 0;
6679
6680 break;
6681
6682 case eEncodingT2:
6683 // if Rn == ’1111’ then SEE LDRH (literal);
6684 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6685 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6686 t = Bits32 (opcode, 15, 12);
6687 n = Bits32 (opcode, 19, 16);
6688 m = Bits32 (opcode, 3, 0);
6689
6690 // index = TRUE; add = TRUE; wback = FALSE;
6691 index = true;
6692 add = true;
6693 wback = false;
6694
6695 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6696 shift_t = SRType_LSL;
6697 shift_n = Bits32 (opcode, 5, 4);
6698
6699 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6700 if ((t == 13) || BadReg (m))
6701 return false;
6702 break;
6703
6704 case eEncodingA1:
6705 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6706 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6707 t = Bits32 (opcode, 15, 12);
6708 n = Bits32 (opcode, 19, 16);
6709 m = Bits32 (opcode, 3, 0);
6710
6711 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6712 index = BitIsSet (opcode, 24);
6713 add = BitIsSet (opcode, 23);
6714 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6715
6716 // (shift_t, shift_n) = (SRType_LSL, 0);
6717 shift_t = SRType_LSL;
6718 shift_n = 0;
6719
6720 // if t == 15 || m == 15 then UNPREDICTABLE;
6721 if ((t == 15) || (m == 15))
6722 return false;
6723
6724 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6725 if (wback && ((n == 15) || (n == t)))
6726 return false;
6727
6728 break;
6729
6730 default:
6731 return false;
6732 }
6733
6734 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6735
6736 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6737 if (!success)
6738 return false;
6739
6740 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6741
6742 addr_t offset_addr;
6743 addr_t address;
6744
6745 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6746 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6747 if (!success)
6748 return false;
6749
6750 if (add)
6751 offset_addr = Rn + offset;
6752 else
6753 offset_addr = Rn - offset;
6754
6755 // address = if index then offset_addr else R[n];
6756 if (index)
6757 address = offset_addr;
6758 else
6759 address = Rn;
6760
6761 // data = MemU[address,2];
6762 Register base_reg;
6763 Register offset_reg;
6764 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6765 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6766
6767 EmulateInstruction::Context context;
6768 context.type = eContextRegisterLoad;
6769 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6770 uint64_t data = MemURead (context, address, 2, 0, &success);
6771 if (!success)
6772 return false;
6773
6774 // if wback then R[n] = offset_addr;
6775 if (wback)
6776 {
6777 context.type = eContextAdjustBaseRegister;
6778 context.SetAddress (offset_addr);
6779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6780 return false;
6781 }
6782
6783 // if UnalignedSupport() || address<0> = ’0’ then
6784 if (UnalignedSupport() || BitIsClear (address, 0))
6785 {
6786 // R[t] = ZeroExtend(data, 32);
6787 context.type = eContextRegisterLoad;
6788 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6789 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6790 return false;
6791 }
6792 else // Can only apply before ARMv7
6793 {
6794 // R[t] = bits(32) UNKNOWN;
6795 WriteBits32Unknown (t);
6796 }
6797 }
6798 return true;
6799}
6800
Caroline Ticea5e28af2011-03-01 21:53:03 +00006801// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6802// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6803// or pre-indexed addressing.
6804bool
6805EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6806{
6807#if 0
6808 if ConditionPassed() then
6809 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6810 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6811 address = if index then offset_addr else R[n];
6812 R[t] = SignExtend(MemU[address,1], 32);
6813 if wback then R[n] = offset_addr;
6814#endif
6815
6816 bool success = false;
6817 const uint32_t opcode = OpcodeAsUnsigned (&success);
6818 if (!success)
6819 return false;
6820
6821 if (ConditionPassed ())
6822 {
6823 uint32_t t;
6824 uint32_t n;
6825 uint32_t imm32;
6826 bool index;
6827 bool add;
6828 bool wback;
6829
6830 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6831 switch (encoding)
6832 {
6833 case eEncodingT1:
6834 // if Rt == ’1111’ then SEE PLI;
6835 // if Rn == ’1111’ then SEE LDRSB (literal);
6836 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6837 t = Bits32 (opcode, 15, 12);
6838 n = Bits32 (opcode, 19, 16);
6839 imm32 = Bits32 (opcode, 11, 0);
6840
6841 // index = TRUE; add = TRUE; wback = FALSE;
6842 index = true;
6843 add = true;
6844 wback = false;
6845
6846 // if t == 13 then UNPREDICTABLE;
6847 if (t == 13)
6848 return false;
6849
6850 break;
6851
6852 case eEncodingT2:
6853 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6854 // if Rn == ’1111’ then SEE LDRSB (literal);
6855 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6856 // if P == ’0’ && W == ’0’ then UNDEFINED;
6857 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6858 return false;
6859
6860 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6861 t = Bits32 (opcode, 15, 12);
6862 n = Bits32 (opcode, 19, 16);
6863 imm32 = Bits32 (opcode, 7, 0);
6864
6865 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6866 index = BitIsSet (opcode, 10);
6867 add = BitIsSet (opcode, 9);
6868 wback = BitIsSet (opcode, 8);
6869
6870 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6871 if (BadReg (t) || (wback && (n == t)))
6872 return false;
6873
6874 break;
6875
6876 case eEncodingA1:
6877 {
6878 // if Rn == ’1111’ then SEE LDRSB (literal);
6879 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6880 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6881 t = Bits32 (opcode, 15, 12);
6882 n = Bits32 (opcode, 19, 16);
6883
6884 uint32_t imm4H = Bits32 (opcode, 11, 8);
6885 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006886 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006887
6888 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6889 index = BitIsSet (opcode, 24);
6890 add = BitIsSet (opcode, 23);
6891 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6892
6893 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6894 if ((t == 15) || (wback && (n == t)))
6895 return false;
6896
6897 break;
6898 }
6899
6900 default:
6901 return false;
6902 }
6903
6904 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6905 if (!success)
6906 return false;
6907
6908 addr_t offset_addr;
6909 addr_t address;
6910
6911 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6912 if (add)
6913 offset_addr = Rn + imm32;
6914 else
6915 offset_addr = Rn - imm32;
6916
6917 // address = if index then offset_addr else R[n];
6918 if (index)
6919 address = offset_addr;
6920 else
6921 address = Rn;
6922
6923 // R[t] = SignExtend(MemU[address,1], 32);
6924 Register base_reg;
6925 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6926
6927 EmulateInstruction::Context context;
6928 context.type = eContextRegisterLoad;
6929 context.SetRegisterPlusOffset (base_reg, address - Rn);
6930
6931 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6932 if (!success)
6933 return false;
6934
6935 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6936 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6937 return false;
6938
6939 // if wback then R[n] = offset_addr;
6940 if (wback)
6941 {
6942 context.type = eContextAdjustBaseRegister;
6943 context.SetAddress (offset_addr);
6944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6945 return false;
6946 }
6947 }
6948
6949 return true;
6950}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006951
Caroline Tice5f593912011-03-01 22:25:17 +00006952// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6953// sign-extends it to form a 32-bit word, and writes tit to a register.
6954bool
6955EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6956{
6957#if 0
6958 if ConditionPassed() then
6959 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6960 base = Align(PC,4);
6961 address = if add then (base + imm32) else (base - imm32);
6962 R[t] = SignExtend(MemU[address,1], 32);
6963#endif
6964
6965 bool success = false;
6966 const uint32_t opcode = OpcodeAsUnsigned (&success);
6967 if (!success)
6968 return false;
6969
6970 if (ConditionPassed ())
6971 {
6972 uint32_t t;
6973 uint32_t imm32;
6974 bool add;
6975
6976 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6977 switch (encoding)
6978 {
6979 case eEncodingT1:
6980 // if Rt == ’1111’ then SEE PLI;
6981 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6982 t = Bits32 (opcode, 15, 12);
6983 imm32 = Bits32 (opcode, 11, 0);
6984 add = BitIsSet (opcode, 23);
6985
6986 // if t == 13 then UNPREDICTABLE;
6987 if (t == 13)
6988 return false;
6989
6990 break;
6991
6992 case eEncodingA1:
6993 {
6994 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6995 t = Bits32 (opcode, 15, 12);
6996 uint32_t imm4H = Bits32 (opcode, 11, 8);
6997 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006998 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006999 add = BitIsSet (opcode, 23);
7000
7001 // if t == 15 then UNPREDICTABLE;
7002 if (t == 15)
7003 return false;
7004
7005 break;
7006 }
7007
7008 default:
7009 return false;
7010 }
7011
7012 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007013 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007014 if (!success)
7015 return false;
7016 uint64_t base = AlignPC (pc_value);
7017
7018 // address = if add then (base + imm32) else (base - imm32);
7019 addr_t address;
7020 if (add)
7021 address = base + imm32;
7022 else
7023 address = base - imm32;
7024
7025 // R[t] = SignExtend(MemU[address,1], 32);
7026 Register base_reg;
7027 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7028
7029 EmulateInstruction::Context context;
7030 context.type = eContextRegisterLoad;
7031 context.SetRegisterPlusOffset (base_reg, address - base);
7032
7033 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7034 if (!success)
7035 return false;
7036
7037 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7038 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7039 return false;
7040 }
7041 return true;
7042}
7043
Caroline Tice672f3112011-03-01 23:55:59 +00007044// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7045// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7046// shifted left by 0, 1, 2, or 3 bits.
7047bool
7048EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
7049{
7050#if 0
7051 if ConditionPassed() then
7052 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7053 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7054 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7055 address = if index then offset_addr else R[n];
7056 R[t] = SignExtend(MemU[address,1], 32);
7057 if wback then R[n] = offset_addr;
7058#endif
7059
7060 bool success = false;
7061 const uint32_t opcode = OpcodeAsUnsigned (&success);
7062 if (!success)
7063 return false;
7064
7065 if (ConditionPassed ())
7066 {
7067 uint32_t t;
7068 uint32_t n;
7069 uint32_t m;
7070 bool index;
7071 bool add;
7072 bool wback;
7073 ARM_ShifterType shift_t;
7074 uint32_t shift_n;
7075
7076 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7077 switch (encoding)
7078 {
7079 case eEncodingT1:
7080 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7081 t = Bits32 (opcode, 2, 0);
7082 n = Bits32 (opcode, 5, 3);
7083 m = Bits32 (opcode, 8, 6);
7084
7085 // index = TRUE; add = TRUE; wback = FALSE;
7086 index = true;
7087 add = true;
7088 wback = false;
7089
7090 // (shift_t, shift_n) = (SRType_LSL, 0);
7091 shift_t = SRType_LSL;
7092 shift_n = 0;
7093
7094 break;
7095
7096 case eEncodingT2:
7097 // if Rt == ’1111’ then SEE PLI;
7098 // if Rn == ’1111’ then SEE LDRSB (literal);
7099 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7100 t = Bits32 (opcode, 15, 12);
7101 n = Bits32 (opcode, 19, 16);
7102 m = Bits32 (opcode, 3, 0);
7103
7104 // index = TRUE; add = TRUE; wback = FALSE;
7105 index = true;
7106 add = true;
7107 wback = false;
7108
7109 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7110 shift_t = SRType_LSL;
7111 shift_n = Bits32 (opcode, 5, 4);
7112
7113 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7114 if ((t == 13) || BadReg (m))
7115 return false;
7116 break;
7117
7118 case eEncodingA1:
7119 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
7120 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7121 t = Bits32 (opcode, 15, 12);
7122 n = Bits32 (opcode, 19, 16);
7123 m = Bits32 (opcode, 3, 0);
7124
7125 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7126 index = BitIsSet (opcode, 24);
7127 add = BitIsSet (opcode, 23);
7128 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7129
7130 // (shift_t, shift_n) = (SRType_LSL, 0);
7131 shift_t = SRType_LSL;
7132 shift_n = 0;
7133
7134 // if t == 15 || m == 15 then UNPREDICTABLE;
7135 if ((t == 15) || (m == 15))
7136 return false;
7137
7138 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7139 if (wback && ((n == 15) || (n == t)))
7140 return false;
7141 break;
7142
7143 default:
7144 return false;
7145 }
7146
7147 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7148 if (!success)
7149 return false;
7150
7151 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7152 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7153
7154 addr_t offset_addr;
7155 addr_t address;
7156
7157 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7158 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7159 if (!success)
7160 return false;
7161
7162 if (add)
7163 offset_addr = Rn + offset;
7164 else
7165 offset_addr = Rn - offset;
7166
7167 // address = if index then offset_addr else R[n];
7168 if (index)
7169 address = offset_addr;
7170 else
7171 address = Rn;
7172
7173 // R[t] = SignExtend(MemU[address,1], 32);
7174 Register base_reg;
7175 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7176 Register offset_reg;
7177 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7178
7179 EmulateInstruction::Context context;
7180 context.type = eContextRegisterLoad;
7181 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7182
7183 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7184 if (!success)
7185 return false;
7186
7187 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7189 return false;
7190
7191 // if wback then R[n] = offset_addr;
7192 if (wback)
7193 {
7194 context.type = eContextAdjustBaseRegister;
7195 context.SetAddress (offset_addr);
7196 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7197 return false;
7198 }
7199 }
7200 return true;
7201}
7202
Caroline Tice78fb5632011-03-02 00:39:42 +00007203// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7204// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7205// pre-indexed addressing.
7206bool
7207EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
7208{
7209#if 0
7210 if ConditionPassed() then
7211 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7212 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7213 address = if index then offset_addr else R[n];
7214 data = MemU[address,2];
7215 if wback then R[n] = offset_addr;
7216 if UnalignedSupport() || address<0> = ’0’ then
7217 R[t] = SignExtend(data, 32);
7218 else // Can only apply before ARMv7
7219 R[t] = bits(32) UNKNOWN;
7220#endif
7221
7222 bool success = false;
7223 const uint32_t opcode = OpcodeAsUnsigned (&success);
7224 if (!success)
7225 return false;
7226
7227 if (ConditionPassed())
7228 {
7229 uint32_t t;
7230 uint32_t n;
7231 uint32_t imm32;
7232 bool index;
7233 bool add;
7234 bool wback;
7235
7236 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7237 switch (encoding)
7238 {
7239 case eEncodingT1:
7240 // if Rn == ’1111’ then SEE LDRSH (literal);
7241 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7242 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7243 t = Bits32 (opcode, 15, 12);
7244 n = Bits32 (opcode, 19, 16);
7245 imm32 = Bits32 (opcode, 11, 0);
7246
7247 // index = TRUE; add = TRUE; wback = FALSE;
7248 index = true;
7249 add = true;
7250 wback = false;
7251
7252 // if t == 13 then UNPREDICTABLE;
7253 if (t == 13)
7254 return false;
7255
7256 break;
7257
7258 case eEncodingT2:
7259 // if Rn == ’1111’ then SEE LDRSH (literal);
7260 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7261 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7262 // if P == ’0’ && W == ’0’ then UNDEFINED;
7263 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7264 return false;
7265
7266 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7267 t = Bits32 (opcode, 15, 12);
7268 n = Bits32 (opcode, 19, 16);
7269 imm32 = Bits32 (opcode, 7, 0);
7270
7271 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7272 index = BitIsSet (opcode, 10);
7273 add = BitIsSet (opcode, 9);
7274 wback = BitIsSet (opcode, 8);
7275
7276 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7277 if (BadReg (t) || (wback && (n == t)))
7278 return false;
7279
7280 break;
7281
7282 case eEncodingA1:
7283 {
7284 // if Rn == ’1111’ then SEE LDRSH (literal);
7285 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7286 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7287 t = Bits32 (opcode, 15, 12);
7288 n = Bits32 (opcode, 19, 16);
7289 uint32_t imm4H = Bits32 (opcode, 11,8);
7290 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007291 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007292
7293 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7294 index = BitIsSet (opcode, 24);
7295 add = BitIsSet (opcode, 23);
7296 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7297
7298 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7299 if ((t == 15) || (wback && (n == t)))
7300 return false;
7301
7302 break;
7303 }
7304
7305 default:
7306 return false;
7307 }
7308
7309 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7310 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7311 if (!success)
7312 return false;
7313
7314 addr_t offset_addr;
7315 if (add)
7316 offset_addr = Rn + imm32;
7317 else
7318 offset_addr = Rn - imm32;
7319
7320 // address = if index then offset_addr else R[n];
7321 addr_t address;
7322 if (index)
7323 address = offset_addr;
7324 else
7325 address = Rn;
7326
7327 // data = MemU[address,2];
7328 Register base_reg;
7329 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7330
7331 EmulateInstruction::Context context;
7332 context.type = eContextRegisterLoad;
7333 context.SetRegisterPlusOffset (base_reg, address - Rn);
7334
7335 uint64_t data = MemURead (context, address, 2, 0, &success);
7336 if (!success)
7337 return false;
7338
7339 // if wback then R[n] = offset_addr;
7340 if (wback)
7341 {
7342 context.type = eContextAdjustBaseRegister;
7343 context.SetAddress (offset_addr);
7344 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7345 return false;
7346 }
7347
7348 // if UnalignedSupport() || address<0> = ’0’ then
7349 if (UnalignedSupport() || BitIsClear (address, 0))
7350 {
7351 // R[t] = SignExtend(data, 32);
7352 int64_t signed_data = llvm::SignExtend64<16>(data);
7353 context.type = eContextRegisterLoad;
7354 context.SetRegisterPlusOffset (base_reg, address - Rn);
7355 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7356 return false;
7357 }
7358 else // Can only apply before ARMv7
7359 {
7360 // R[t] = bits(32) UNKNOWN;
7361 WriteBits32Unknown (t);
7362 }
7363 }
7364 return true;
7365}
7366
Caroline Ticed2fac092011-03-02 19:45:34 +00007367// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7368// sign-extends it to from a 32-bit word, and writes it to a register.
7369bool
7370EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7371{
7372#if 0
7373 if ConditionPassed() then
7374 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7375 base = Align(PC,4);
7376 address = if add then (base + imm32) else (base - imm32);
7377 data = MemU[address,2];
7378 if UnalignedSupport() || address<0> = ’0’ then
7379 R[t] = SignExtend(data, 32);
7380 else // Can only apply before ARMv7
7381 R[t] = bits(32) UNKNOWN;
7382#endif
7383
7384 bool success = false;
7385 const uint32_t opcode = OpcodeAsUnsigned (&success);
7386 if (!success)
7387 return false;
7388
7389 if (ConditionPassed())
7390 {
7391 uint32_t t;
7392 uint32_t imm32;
7393 bool add;
7394
7395 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7396 switch (encoding)
7397 {
7398 case eEncodingT1:
7399 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7400 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7401 t = Bits32 (opcode, 15, 12);
7402 imm32 = Bits32 (opcode, 11, 0);
7403 add = BitIsSet (opcode, 23);
7404
7405 // if t == 13 then UNPREDICTABLE;
7406 if (t == 13)
7407 return false;
7408
7409 break;
7410
7411 case eEncodingA1:
7412 {
7413 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7414 t = Bits32 (opcode, 15, 12);
7415 uint32_t imm4H = Bits32 (opcode, 11, 8);
7416 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007417 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007418 add = BitIsSet (opcode, 23);
7419
7420 // if t == 15 then UNPREDICTABLE;
7421 if (t == 15)
7422 return false;
7423
7424 break;
7425 }
7426 default:
7427 return false;
7428 }
7429
7430 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007431 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007432 if (!success)
7433 return false;
7434
7435 uint64_t base = AlignPC (pc_value);
7436
7437 addr_t address;
7438 // address = if add then (base + imm32) else (base - imm32);
7439 if (add)
7440 address = base + imm32;
7441 else
7442 address = base - imm32;
7443
7444 // data = MemU[address,2];
7445 Register base_reg;
7446 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7447
7448 EmulateInstruction::Context context;
7449 context.type = eContextRegisterLoad;
7450 context.SetRegisterPlusOffset (base_reg, imm32);
7451
7452 uint64_t data = MemURead (context, address, 2, 0, &success);
7453 if (!success)
7454 return false;
7455
7456 // if UnalignedSupport() || address<0> = ’0’ then
7457 if (UnalignedSupport() || BitIsClear (address, 0))
7458 {
7459 // R[t] = SignExtend(data, 32);
7460 int64_t signed_data = llvm::SignExtend64<16>(data);
7461 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7462 return false;
7463 }
7464 else // Can only apply before ARMv7
7465 {
7466 // R[t] = bits(32) UNKNOWN;
7467 WriteBits32Unknown (t);
7468 }
7469 }
7470 return true;
7471}
7472
Caroline Tice291a3e92011-03-02 21:13:44 +00007473// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7474// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7475// shifted left by 0, 1, 2, or 3 bits.
7476bool
7477EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7478{
7479#if 0
7480 if ConditionPassed() then
7481 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7482 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7483 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7484 address = if index then offset_addr else R[n];
7485 data = MemU[address,2];
7486 if wback then R[n] = offset_addr;
7487 if UnalignedSupport() || address<0> = ’0’ then
7488 R[t] = SignExtend(data, 32);
7489 else // Can only apply before ARMv7
7490 R[t] = bits(32) UNKNOWN;
7491#endif
7492
7493 bool success = false;
7494 const uint32_t opcode = OpcodeAsUnsigned (&success);
7495 if (!success)
7496 return false;
7497
7498 if (ConditionPassed())
7499 {
7500 uint32_t t;
7501 uint32_t n;
7502 uint32_t m;
7503 bool index;
7504 bool add;
7505 bool wback;
7506 ARM_ShifterType shift_t;
7507 uint32_t shift_n;
7508
7509 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7510 switch (encoding)
7511 {
7512 case eEncodingT1:
7513 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7514 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7515 t = Bits32 (opcode, 2, 0);
7516 n = Bits32 (opcode, 5, 3);
7517 m = Bits32 (opcode, 8, 6);
7518
7519 // index = TRUE; add = TRUE; wback = FALSE;
7520 index = true;
7521 add = true;
7522 wback = false;
7523
7524 // (shift_t, shift_n) = (SRType_LSL, 0);
7525 shift_t = SRType_LSL;
7526 shift_n = 0;
7527
7528 break;
7529
7530 case eEncodingT2:
7531 // if Rn == ’1111’ then SEE LDRSH (literal);
7532 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7533 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7534 t = Bits32 (opcode, 15, 12);
7535 n = Bits32 (opcode, 19, 16);
7536 m = Bits32 (opcode, 3, 0);
7537
7538 // index = TRUE; add = TRUE; wback = FALSE;
7539 index = true;
7540 add = true;
7541 wback = false;
7542
7543 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7544 shift_t = SRType_LSL;
7545 shift_n = Bits32 (opcode, 5, 4);
7546
7547 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7548 if ((t == 13) || BadReg (m))
7549 return false;
7550
7551 break;
7552
7553 case eEncodingA1:
7554 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7555 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7556 t = Bits32 (opcode, 15, 12);
7557 n = Bits32 (opcode, 19, 16);
7558 m = Bits32 (opcode, 3, 0);
7559
7560 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7561 index = BitIsSet (opcode, 24);
7562 add = BitIsSet (opcode, 23);
7563 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7564
7565 // (shift_t, shift_n) = (SRType_LSL, 0);
7566 shift_t = SRType_LSL;
7567 shift_n = 0;
7568
7569 // if t == 15 || m == 15 then UNPREDICTABLE;
7570 if ((t == 15) || (m == 15))
7571 return false;
7572
7573 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7574 if (wback && ((n == 15) || (n == t)))
7575 return false;
7576
7577 break;
7578
7579 default:
7580 break;
7581 }
7582
7583 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7584 if (!success)
7585 return false;
7586
7587 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7588 if (!success)
7589 return false;
7590
7591 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7592 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7593
7594 addr_t offset_addr;
7595 addr_t address;
7596
7597 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7598 if (add)
7599 offset_addr = Rn + offset;
7600 else
7601 offset_addr = Rn - offset;
7602
7603 // address = if index then offset_addr else R[n];
7604 if (index)
7605 address = offset_addr;
7606 else
7607 address = Rn;
7608
7609 // data = MemU[address,2];
7610 Register base_reg;
7611 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7612
7613 Register offset_reg;
7614 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7615
7616 EmulateInstruction::Context context;
7617 context.type = eContextRegisterLoad;
7618 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7619
7620 uint64_t data = MemURead (context, address, 2, 0, &success);
7621 if (!success)
7622 return false;
7623
7624 // if wback then R[n] = offset_addr;
7625 if (wback)
7626 {
7627 context.type = eContextAdjustBaseRegister;
7628 context.SetAddress (offset_addr);
7629 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7630 return false;
7631 }
7632
7633 // if UnalignedSupport() || address<0> = ’0’ then
7634 if (UnalignedSupport() || BitIsClear (address, 0))
7635 {
7636 // R[t] = SignExtend(data, 32);
7637 context.type = eContextRegisterLoad;
7638 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7639
7640 int64_t signed_data = llvm::SignExtend64<16>(data);
7641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7642 return false;
7643 }
7644 else // Can only apply before ARMv7
7645 {
7646 // R[t] = bits(32) UNKNOWN;
7647 WriteBits32Unknown (t);
7648 }
7649 }
7650 return true;
7651}
Caroline Tice6bf65162011-03-03 17:42:58 +00007652
7653// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7654// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7655bool
7656EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7657{
7658#if 0
7659 if ConditionPassed() then
7660 EncodingSpecificOperations();
7661 rotated = ROR(R[m], rotation);
7662 R[d] = SignExtend(rotated<7:0>, 32);
7663#endif
7664
7665 bool success = false;
7666 const uint32_t opcode = OpcodeAsUnsigned (&success);
7667 if (!success)
7668 return false;
7669
7670 if (ConditionPassed())
7671 {
7672 uint32_t d;
7673 uint32_t m;
7674 uint32_t rotation;
7675
7676 // EncodingSpecificOperations();
7677 switch (encoding)
7678 {
7679 case eEncodingT1:
7680 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7681 d = Bits32 (opcode, 2, 0);
7682 m = Bits32 (opcode, 5, 3);
7683 rotation = 0;
7684
7685 break;
7686
7687 case eEncodingT2:
7688 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7689 d = Bits32 (opcode, 11, 8);
7690 m = Bits32 (opcode, 3, 0);
7691 rotation = Bits32 (opcode, 5, 4) << 3;
7692
7693 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7694 if (BadReg (d) || BadReg (m))
7695 return false;
7696
7697 break;
7698
7699 case eEncodingA1:
7700 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7701 d = Bits32 (opcode, 15, 12);
7702 m = Bits32 (opcode, 3, 0);
7703 rotation = Bits32 (opcode, 11, 10) << 3;
7704
7705 // if d == 15 || m == 15 then UNPREDICTABLE;
7706 if ((d == 15) || (m == 15))
7707 return false;
7708
7709 break;
7710
7711 default:
7712 return false;
7713 }
7714
Caroline Tice868198b2011-03-03 18:04:49 +00007715 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7716 if (!success)
7717 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007718
7719 // rotated = ROR(R[m], rotation);
7720 uint64_t rotated = ROR (Rm, rotation);
7721
7722 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007723 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007724
7725 Register source_reg;
7726 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7727
7728 EmulateInstruction::Context context;
7729 context.type = eContextRegisterLoad;
7730 context.SetRegister (source_reg);
7731
Caroline Tice8ce96d92011-03-03 18:27:17 +00007732 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007733 return false;
7734 }
7735 return true;
7736}
Caroline Tice291a3e92011-03-02 21:13:44 +00007737
Caroline Tice868198b2011-03-03 18:04:49 +00007738// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7739// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7740bool
7741EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7742{
7743#if 0
7744 if ConditionPassed() then
7745 EncodingSpecificOperations();
7746 rotated = ROR(R[m], rotation);
7747 R[d] = SignExtend(rotated<15:0>, 32);
7748#endif
7749
7750 bool success = false;
7751 const uint32_t opcode = OpcodeAsUnsigned (&success);
7752 if (!success)
7753 return false;
7754
7755 if (ConditionPassed())
7756 {
7757 uint32_t d;
7758 uint32_t m;
7759 uint32_t rotation;
7760
7761 // EncodingSpecificOperations();
7762 switch (encoding)
7763 {
7764 case eEncodingT1:
7765 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7766 d = Bits32 (opcode, 2, 0);
7767 m = Bits32 (opcode, 5, 3);
7768 rotation = 0;
7769
7770 break;
7771
7772 case eEncodingT2:
7773 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7774 d = Bits32 (opcode, 11, 8);
7775 m = Bits32 (opcode, 3, 0);
7776 rotation = Bits32 (opcode, 5, 4) << 3;
7777
7778 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7779 if (BadReg (d) || BadReg (m))
7780 return false;
7781
7782 break;
7783
7784 case eEncodingA1:
7785 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7786 d = Bits32 (opcode, 15, 12);
7787 m = Bits32 (opcode, 3, 0);
7788 rotation = Bits32 (opcode, 11, 10) << 3;
7789
7790 // if d == 15 || m == 15 then UNPREDICTABLE;
7791 if ((d == 15) || (m == 15))
7792 return false;
7793
7794 break;
7795
7796 default:
7797 return false;
7798 }
7799
7800 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7801 if (!success)
7802 return false;
7803
7804 // rotated = ROR(R[m], rotation);
7805 uint64_t rotated = ROR (Rm, rotation);
7806
7807 // R[d] = SignExtend(rotated<15:0>, 32);
7808 Register source_reg;
7809 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7810
7811 EmulateInstruction::Context context;
7812 context.type = eContextRegisterLoad;
7813 context.SetRegister (source_reg);
7814
Caroline Tice8ce96d92011-03-03 18:27:17 +00007815 int64_t data = llvm::SignExtend64<16> (rotated);
7816 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007817 return false;
7818 }
7819
7820 return true;
7821}
7822
Caroline Tice8ce96d92011-03-03 18:27:17 +00007823// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7824// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7825bool
7826EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7827{
7828#if 0
7829 if ConditionPassed() then
7830 EncodingSpecificOperations();
7831 rotated = ROR(R[m], rotation);
7832 R[d] = ZeroExtend(rotated<7:0>, 32);
7833#endif
7834
7835 bool success = false;
7836 const uint32_t opcode = OpcodeAsUnsigned (&success);
7837 if (!success)
7838 return false;
7839
7840 if (ConditionPassed())
7841 {
7842 uint32_t d;
7843 uint32_t m;
7844 uint32_t rotation;
7845
7846 // EncodingSpecificOperations();
7847 switch (encoding)
7848 {
7849 case eEncodingT1:
7850 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7851 d = Bits32 (opcode, 2, 0);
7852 m = Bits32 (opcode, 5, 3);
7853 rotation = 0;
7854
7855 break;
7856
7857 case eEncodingT2:
7858 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7859 d = Bits32 (opcode, 11, 8);
7860 m = Bits32 (opcode, 3, 0);
7861 rotation = Bits32 (opcode, 5, 4) << 3;
7862
7863 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7864 if (BadReg (d) || BadReg (m))
7865 return false;
7866
7867 break;
7868
7869 case eEncodingA1:
7870 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7871 d = Bits32 (opcode, 15, 12);
7872 m = Bits32 (opcode, 3, 0);
7873 rotation = Bits32 (opcode, 11, 10) << 3;
7874
7875 // if d == 15 || m == 15 then UNPREDICTABLE;
7876 if ((d == 15) || (m == 15))
7877 return false;
7878
7879 break;
7880
7881 default:
7882 return false;
7883 }
7884
7885 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7886 if (!success)
7887 return false;
7888
7889 // rotated = ROR(R[m], rotation);
7890 uint64_t rotated = ROR (Rm, rotation);
7891
7892 // R[d] = ZeroExtend(rotated<7:0>, 32);
7893 Register source_reg;
7894 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7895
7896 EmulateInstruction::Context context;
7897 context.type = eContextRegisterLoad;
7898 context.SetRegister (source_reg);
7899
7900 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7901 return false;
7902 }
7903 return true;
7904}
7905
Caroline Tice11555f22011-03-03 18:48:58 +00007906// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7907// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7908bool
7909EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7910{
7911#if 0
7912 if ConditionPassed() then
7913 EncodingSpecificOperations();
7914 rotated = ROR(R[m], rotation);
7915 R[d] = ZeroExtend(rotated<15:0>, 32);
7916#endif
7917
7918 bool success = false;
7919 const uint32_t opcode = OpcodeAsUnsigned (&success);
7920 if (!success)
7921 return false;
7922
7923 if (ConditionPassed ())
7924 {
7925 uint32_t d;
7926 uint32_t m;
7927 uint32_t rotation;
7928
7929 switch (encoding)
7930 {
7931 case eEncodingT1:
7932 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7933 d = Bits32 (opcode, 2, 0);
7934 m = Bits32 (opcode, 5, 3);
7935 rotation = 0;
7936
7937 break;
7938
7939 case eEncodingT2:
7940 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7941 d = Bits32 (opcode, 11, 8);
7942 m = Bits32 (opcode, 3, 0);
7943 rotation = Bits32 (opcode, 5, 4) << 3;
7944
7945 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7946 if (BadReg (d) || BadReg (m))
7947 return false;
7948
7949 break;
7950
7951 case eEncodingA1:
7952 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7953 d = Bits32 (opcode, 15, 12);
7954 m = Bits32 (opcode, 3, 0);
7955 rotation = Bits32 (opcode, 11, 10) << 3;
7956
7957 // if d == 15 || m == 15 then UNPREDICTABLE;
7958 if ((d == 15) || (m == 15))
7959 return false;
7960
7961 break;
7962
7963 default:
7964 return false;
7965 }
7966
7967 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7968 if (!success)
7969 return false;
7970
7971 // rotated = ROR(R[m], rotation);
7972 uint64_t rotated = ROR (Rm, rotation);
7973
7974 // R[d] = ZeroExtend(rotated<15:0>, 32);
7975 Register source_reg;
7976 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7977
7978 EmulateInstruction::Context context;
7979 context.type = eContextRegisterLoad;
7980 context.SetRegister (source_reg);
7981
7982 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7983 return false;
7984 }
7985 return true;
7986}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007987
7988// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7989// word respectively.
7990bool
7991EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7992{
7993#if 0
7994 if ConditionPassed() then
7995 EncodingSpecificOperations();
7996 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7997 UNPREDICTABLE;
7998 else
7999 address = if increment then R[n] else R[n]-8;
8000 if wordhigher then address = address+4;
8001 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8002 BranchWritePC(MemA[address,4]);
8003 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8004#endif
8005
8006 bool success = false;
8007 const uint32_t opcode = OpcodeAsUnsigned (&success);
8008 if (!success)
8009 return false;
8010
8011 if (ConditionPassed())
8012 {
8013 uint32_t n;
8014 bool wback;
8015 bool increment;
8016 bool wordhigher;
8017
8018 // EncodingSpecificOperations();
8019 switch (encoding)
8020 {
8021 case eEncodingT1:
8022 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
8023 n = Bits32 (opcode, 19, 16);
8024 wback = BitIsSet (opcode, 21);
8025 increment = false;
8026 wordhigher = false;
8027
8028 // if n == 15 then UNPREDICTABLE;
8029 if (n == 15)
8030 return false;
8031
8032 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8033 if (InITBlock() && !LastInITBlock())
8034 return false;
8035
8036 break;
8037
8038 case eEncodingT2:
8039 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
8040 n = Bits32 (opcode, 19, 16);
8041 wback = BitIsSet (opcode, 21);
8042 increment = true;
8043 wordhigher = false;
8044
8045 // if n == 15 then UNPREDICTABLE;
8046 if (n == 15)
8047 return false;
8048
8049 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8050 if (InITBlock() && !LastInITBlock())
8051 return false;
8052
8053 break;
8054
8055 case eEncodingA1:
8056 // n = UInt(Rn);
8057 n = Bits32 (opcode, 19, 16);
8058
8059 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
8060 wback = BitIsSet (opcode, 21);
8061 increment = BitIsSet (opcode, 23);
8062 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8063
8064 // if n == 15 then UNPREDICTABLE;
8065 if (n == 15)
8066 return false;
8067
8068 break;
8069
8070 default:
8071 return false;
8072 }
8073
8074 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8075 if (!CurrentModeIsPrivileged ())
8076 // UNPREDICTABLE;
8077 return false;
8078 else
8079 {
8080 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8081 if (!success)
8082 return false;
8083
8084 addr_t address;
8085 // address = if increment then R[n] else R[n]-8;
8086 if (increment)
8087 address = Rn;
8088 else
8089 address = Rn - 8;
8090
8091 // if wordhigher then address = address+4;
8092 if (wordhigher)
8093 address = address + 4;
8094
8095 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8096 Register base_reg;
8097 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8098
8099 EmulateInstruction::Context context;
8100 context.type = eContextReturnFromException;
8101 context.SetRegisterPlusOffset (base_reg, address - Rn);
8102
8103 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8104 if (!success)
8105 return false;
8106
8107 CPSRWriteByInstr (data, 15, true);
8108
8109 // BranchWritePC(MemA[address,4]);
8110 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8111 if (!success)
8112 return false;
8113
8114 BranchWritePC (context, data2);
8115
8116 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8117 if (wback)
8118 {
8119 context.type = eContextAdjustBaseRegister;
8120 if (increment)
8121 {
8122 context.SetOffset (8);
8123 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8124 return false;
8125 }
8126 else
8127 {
8128 context.SetOffset (-8);
8129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8130 return false;
8131 }
8132 } // if wback
8133 }
8134 } // if ConditionPassed()
8135 return true;
8136}
Caroline Tice11555f22011-03-03 18:48:58 +00008137
Johnny Chen2115b412011-02-21 23:42:44 +00008138// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8139// and writes the result to the destination register. It can optionally update the condition flags based on
8140// the result.
8141bool
8142EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
8143{
8144#if 0
8145 // ARM pseudo code...
8146 if ConditionPassed() then
8147 EncodingSpecificOperations();
8148 result = R[n] EOR imm32;
8149 if d == 15 then // Can only occur for ARM encoding
8150 ALUWritePC(result); // setflags is always FALSE here
8151 else
8152 R[d] = result;
8153 if setflags then
8154 APSR.N = result<31>;
8155 APSR.Z = IsZeroBit(result);
8156 APSR.C = carry;
8157 // APSR.V unchanged
8158#endif
8159
8160 bool success = false;
8161 const uint32_t opcode = OpcodeAsUnsigned (&success);
8162 if (!success)
8163 return false;
8164
8165 if (ConditionPassed())
8166 {
8167 uint32_t Rd, Rn;
8168 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8169 bool setflags;
8170 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8171 switch (encoding)
8172 {
8173 case eEncodingT1:
8174 Rd = Bits32(opcode, 11, 8);
8175 Rn = Bits32(opcode, 19, 16);
8176 setflags = BitIsSet(opcode, 20);
8177 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8178 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8179 if (Rd == 15 && setflags)
8180 return EmulateTEQImm(eEncodingT1);
8181 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8182 return false;
8183 break;
8184 case eEncodingA1:
8185 Rd = Bits32(opcode, 15, 12);
8186 Rn = Bits32(opcode, 19, 16);
8187 setflags = BitIsSet(opcode, 20);
8188 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8189 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8190 // TODO: Emulate SUBS PC, LR and related instructions.
8191 if (Rd == 15 && setflags)
8192 return false;
8193 break;
8194 default:
8195 return false;
8196 }
8197
8198 // Read the first operand.
8199 uint32_t val1 = ReadCoreReg(Rn, &success);
8200 if (!success)
8201 return false;
8202
8203 uint32_t result = val1 ^ imm32;
8204
8205 EmulateInstruction::Context context;
8206 context.type = EmulateInstruction::eContextImmediate;
8207 context.SetNoArgs ();
8208
8209 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8210 return false;
8211 }
8212 return true;
8213}
8214
8215// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8216// optionally-shifted register value, and writes the result to the destination register.
8217// It can optionally update the condition flags based on the result.
8218bool
8219EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
8220{
8221#if 0
8222 // ARM pseudo code...
8223 if ConditionPassed() then
8224 EncodingSpecificOperations();
8225 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8226 result = R[n] EOR shifted;
8227 if d == 15 then // Can only occur for ARM encoding
8228 ALUWritePC(result); // setflags is always FALSE here
8229 else
8230 R[d] = result;
8231 if setflags then
8232 APSR.N = result<31>;
8233 APSR.Z = IsZeroBit(result);
8234 APSR.C = carry;
8235 // APSR.V unchanged
8236#endif
8237
8238 bool success = false;
8239 const uint32_t opcode = OpcodeAsUnsigned (&success);
8240 if (!success)
8241 return false;
8242
8243 if (ConditionPassed())
8244 {
8245 uint32_t Rd, Rn, Rm;
8246 ARM_ShifterType shift_t;
8247 uint32_t shift_n; // the shift applied to the value read from Rm
8248 bool setflags;
8249 uint32_t carry;
8250 switch (encoding)
8251 {
8252 case eEncodingT1:
8253 Rd = Rn = Bits32(opcode, 2, 0);
8254 Rm = Bits32(opcode, 5, 3);
8255 setflags = !InITBlock();
8256 shift_t = SRType_LSL;
8257 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008258 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008259 case eEncodingT2:
8260 Rd = Bits32(opcode, 11, 8);
8261 Rn = Bits32(opcode, 19, 16);
8262 Rm = Bits32(opcode, 3, 0);
8263 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008264 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8265 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008266 if (Rd == 15 && setflags)
8267 return EmulateTEQReg(eEncodingT1);
8268 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8269 return false;
8270 break;
8271 case eEncodingA1:
8272 Rd = Bits32(opcode, 15, 12);
8273 Rn = Bits32(opcode, 19, 16);
8274 Rm = Bits32(opcode, 3, 0);
8275 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008276 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008277 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8278 // TODO: Emulate SUBS PC, LR and related instructions.
8279 if (Rd == 15 && setflags)
8280 return false;
8281 break;
8282 default:
8283 return false;
8284 }
8285
8286 // Read the first operand.
8287 uint32_t val1 = ReadCoreReg(Rn, &success);
8288 if (!success)
8289 return false;
8290
8291 // Read the second operand.
8292 uint32_t val2 = ReadCoreReg(Rm, &success);
8293 if (!success)
8294 return false;
8295
8296 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8297 uint32_t result = val1 ^ shifted;
8298
8299 EmulateInstruction::Context context;
8300 context.type = EmulateInstruction::eContextImmediate;
8301 context.SetNoArgs ();
8302
8303 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8304 return false;
8305 }
8306 return true;
8307}
8308
Johnny Chen7c5234d2011-02-18 23:41:11 +00008309// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8310// writes the result to the destination register. It can optionally update the condition flags based
8311// on the result.
8312bool
8313EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8314{
8315#if 0
8316 // ARM pseudo code...
8317 if ConditionPassed() then
8318 EncodingSpecificOperations();
8319 result = R[n] OR imm32;
8320 if d == 15 then // Can only occur for ARM encoding
8321 ALUWritePC(result); // setflags is always FALSE here
8322 else
8323 R[d] = result;
8324 if setflags then
8325 APSR.N = result<31>;
8326 APSR.Z = IsZeroBit(result);
8327 APSR.C = carry;
8328 // APSR.V unchanged
8329#endif
8330
8331 bool success = false;
8332 const uint32_t opcode = OpcodeAsUnsigned (&success);
8333 if (!success)
8334 return false;
8335
8336 if (ConditionPassed())
8337 {
8338 uint32_t Rd, Rn;
8339 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8340 bool setflags;
8341 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8342 switch (encoding)
8343 {
8344 case eEncodingT1:
8345 Rd = Bits32(opcode, 11, 8);
8346 Rn = Bits32(opcode, 19, 16);
8347 setflags = BitIsSet(opcode, 20);
8348 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8349 // if Rn == ‘1111’ then SEE MOV (immediate);
8350 if (Rn == 15)
8351 return EmulateMOVRdImm(eEncodingT2);
8352 if (BadReg(Rd) || Rn == 13)
8353 return false;
8354 break;
8355 case eEncodingA1:
8356 Rd = Bits32(opcode, 15, 12);
8357 Rn = Bits32(opcode, 19, 16);
8358 setflags = BitIsSet(opcode, 20);
8359 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8360 // TODO: Emulate SUBS PC, LR and related instructions.
8361 if (Rd == 15 && setflags)
8362 return false;
8363 break;
8364 default:
8365 return false;
8366 }
8367
8368 // Read the first operand.
8369 uint32_t val1 = ReadCoreReg(Rn, &success);
8370 if (!success)
8371 return false;
8372
8373 uint32_t result = val1 | imm32;
8374
8375 EmulateInstruction::Context context;
8376 context.type = EmulateInstruction::eContextImmediate;
8377 context.SetNoArgs ();
8378
8379 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8380 return false;
8381 }
8382 return true;
8383}
8384
8385// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8386// value, and writes the result to the destination register. It can optionally update the condition flags based
8387// on the result.
8388bool
8389EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8390{
8391#if 0
8392 // ARM pseudo code...
8393 if ConditionPassed() then
8394 EncodingSpecificOperations();
8395 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8396 result = R[n] OR shifted;
8397 if d == 15 then // Can only occur for ARM encoding
8398 ALUWritePC(result); // setflags is always FALSE here
8399 else
8400 R[d] = result;
8401 if setflags then
8402 APSR.N = result<31>;
8403 APSR.Z = IsZeroBit(result);
8404 APSR.C = carry;
8405 // APSR.V unchanged
8406#endif
8407
8408 bool success = false;
8409 const uint32_t opcode = OpcodeAsUnsigned (&success);
8410 if (!success)
8411 return false;
8412
8413 if (ConditionPassed())
8414 {
8415 uint32_t Rd, Rn, Rm;
8416 ARM_ShifterType shift_t;
8417 uint32_t shift_n; // the shift applied to the value read from Rm
8418 bool setflags;
8419 uint32_t carry;
8420 switch (encoding)
8421 {
8422 case eEncodingT1:
8423 Rd = Rn = Bits32(opcode, 2, 0);
8424 Rm = Bits32(opcode, 5, 3);
8425 setflags = !InITBlock();
8426 shift_t = SRType_LSL;
8427 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008428 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008429 case eEncodingT2:
8430 Rd = Bits32(opcode, 11, 8);
8431 Rn = Bits32(opcode, 19, 16);
8432 Rm = Bits32(opcode, 3, 0);
8433 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008434 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8435 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008436 if (Rn == 15)
8437 return EmulateMOVRdRm(eEncodingT3);
8438 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8439 return false;
8440 break;
8441 case eEncodingA1:
8442 Rd = Bits32(opcode, 15, 12);
8443 Rn = Bits32(opcode, 19, 16);
8444 Rm = Bits32(opcode, 3, 0);
8445 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008446 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008447 // TODO: Emulate SUBS PC, LR and related instructions.
8448 if (Rd == 15 && setflags)
8449 return false;
8450 break;
8451 default:
8452 return false;
8453 }
8454
8455 // Read the first operand.
8456 uint32_t val1 = ReadCoreReg(Rn, &success);
8457 if (!success)
8458 return false;
8459
8460 // Read the second operand.
8461 uint32_t val2 = ReadCoreReg(Rm, &success);
8462 if (!success)
8463 return false;
8464
8465 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008466 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008467
8468 EmulateInstruction::Context context;
8469 context.type = EmulateInstruction::eContextImmediate;
8470 context.SetNoArgs ();
8471
8472 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8473 return false;
8474 }
8475 return true;
8476}
8477
Johnny Chened32e7c2011-02-22 23:42:58 +00008478// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8479// the destination register. It can optionally update the condition flags based on the result.
8480bool
8481EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8482{
8483#if 0
8484 // ARM pseudo code...
8485 if ConditionPassed() then
8486 EncodingSpecificOperations();
8487 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8488 if d == 15 then // Can only occur for ARM encoding
8489 ALUWritePC(result); // setflags is always FALSE here
8490 else
8491 R[d] = result;
8492 if setflags then
8493 APSR.N = result<31>;
8494 APSR.Z = IsZeroBit(result);
8495 APSR.C = carry;
8496 APSR.V = overflow;
8497#endif
8498
8499 bool success = false;
8500 const uint32_t opcode = OpcodeAsUnsigned (&success);
8501 if (!success)
8502 return false;
8503
8504 uint32_t Rd; // the destination register
8505 uint32_t Rn; // the first operand
8506 bool setflags;
8507 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8508 switch (encoding) {
8509 case eEncodingT1:
8510 Rd = Bits32(opcode, 2, 0);
8511 Rn = Bits32(opcode, 5, 3);
8512 setflags = !InITBlock();
8513 imm32 = 0;
8514 break;
8515 case eEncodingT2:
8516 Rd = Bits32(opcode, 11, 8);
8517 Rn = Bits32(opcode, 19, 16);
8518 setflags = BitIsSet(opcode, 20);
8519 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8520 if (BadReg(Rd) || BadReg(Rn))
8521 return false;
8522 break;
8523 case eEncodingA1:
8524 Rd = Bits32(opcode, 15, 12);
8525 Rn = Bits32(opcode, 19, 16);
8526 setflags = BitIsSet(opcode, 20);
8527 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8528 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8529 // TODO: Emulate SUBS PC, LR and related instructions.
8530 if (Rd == 15 && setflags)
8531 return false;
8532 break;
8533 default:
8534 return false;
8535 }
8536 // Read the register value from the operand register Rn.
8537 uint32_t reg_val = ReadCoreReg(Rn, &success);
8538 if (!success)
8539 return false;
8540
8541 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8542
8543 EmulateInstruction::Context context;
8544 context.type = EmulateInstruction::eContextImmediate;
8545 context.SetNoArgs ();
8546
8547 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8548 return false;
8549
8550 return true;
8551}
8552
8553// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8554// result to the destination register. It can optionally update the condition flags based on the result.
8555bool
8556EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8557{
8558#if 0
8559 // ARM pseudo code...
8560 if ConditionPassed() then
8561 EncodingSpecificOperations();
8562 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8563 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8564 if d == 15 then // Can only occur for ARM encoding
8565 ALUWritePC(result); // setflags is always FALSE here
8566 else
8567 R[d] = result;
8568 if setflags then
8569 APSR.N = result<31>;
8570 APSR.Z = IsZeroBit(result);
8571 APSR.C = carry;
8572 APSR.V = overflow;
8573#endif
8574
8575 bool success = false;
8576 const uint32_t opcode = OpcodeAsUnsigned (&success);
8577 if (!success)
8578 return false;
8579
8580 uint32_t Rd; // the destination register
8581 uint32_t Rn; // the first operand
8582 uint32_t Rm; // the second operand
8583 bool setflags;
8584 ARM_ShifterType shift_t;
8585 uint32_t shift_n; // the shift applied to the value read from Rm
8586 switch (encoding) {
8587 case eEncodingT1:
8588 Rd = Bits32(opcode, 11, 8);
8589 Rn = Bits32(opcode, 19, 16);
8590 Rm = Bits32(opcode, 3, 0);
8591 setflags = BitIsSet(opcode, 20);
8592 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8593 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8594 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8595 return false;
8596 break;
8597 case eEncodingA1:
8598 Rd = Bits32(opcode, 15, 12);
8599 Rn = Bits32(opcode, 19, 16);
8600 Rm = Bits32(opcode, 3, 0);
8601 setflags = BitIsSet(opcode, 20);
8602 shift_n = DecodeImmShiftARM(opcode, shift_t);
8603 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8604 // TODO: Emulate SUBS PC, LR and related instructions.
8605 if (Rd == 15 && setflags)
8606 return false;
8607 break;
8608 default:
8609 return false;
8610 }
8611 // Read the register value from register Rn.
8612 uint32_t val1 = ReadCoreReg(Rn, &success);
8613 if (!success)
8614 return false;
8615
8616 // Read the register value from register Rm.
8617 uint32_t val2 = ReadCoreReg(Rm, &success);
8618 if (!success)
8619 return false;
8620
8621 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8622 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8623
8624 EmulateInstruction::Context context;
8625 context.type = EmulateInstruction::eContextImmediate;
8626 context.SetNoArgs();
8627 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8628 return false;
8629
8630 return true;
8631}
8632
Johnny Chen90e607b2011-02-23 00:07:09 +00008633// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8634// an immediate value, and writes the result to the destination register. It can optionally update the condition
8635// flags based on the result.
8636bool
8637EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8638{
8639#if 0
8640 // ARM pseudo code...
8641 if ConditionPassed() then
8642 EncodingSpecificOperations();
8643 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8644 if d == 15 then
8645 ALUWritePC(result); // setflags is always FALSE here
8646 else
8647 R[d] = result;
8648 if setflags then
8649 APSR.N = result<31>;
8650 APSR.Z = IsZeroBit(result);
8651 APSR.C = carry;
8652 APSR.V = overflow;
8653#endif
8654
8655 bool success = false;
8656 const uint32_t opcode = OpcodeAsUnsigned (&success);
8657 if (!success)
8658 return false;
8659
8660 uint32_t Rd; // the destination register
8661 uint32_t Rn; // the first operand
8662 bool setflags;
8663 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8664 switch (encoding) {
8665 case eEncodingA1:
8666 Rd = Bits32(opcode, 15, 12);
8667 Rn = Bits32(opcode, 19, 16);
8668 setflags = BitIsSet(opcode, 20);
8669 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8670 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8671 // TODO: Emulate SUBS PC, LR and related instructions.
8672 if (Rd == 15 && setflags)
8673 return false;
8674 break;
8675 default:
8676 return false;
8677 }
8678 // Read the register value from the operand register Rn.
8679 uint32_t reg_val = ReadCoreReg(Rn, &success);
8680 if (!success)
8681 return false;
8682
8683 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8684
8685 EmulateInstruction::Context context;
8686 context.type = EmulateInstruction::eContextImmediate;
8687 context.SetNoArgs ();
8688
8689 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8690 return false;
8691
8692 return true;
8693}
8694
8695// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8696// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8697// condition flags based on the result.
8698bool
8699EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8700{
8701#if 0
8702 // ARM pseudo code...
8703 if ConditionPassed() then
8704 EncodingSpecificOperations();
8705 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8706 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8707 if d == 15 then
8708 ALUWritePC(result); // setflags is always FALSE here
8709 else
8710 R[d] = result;
8711 if setflags then
8712 APSR.N = result<31>;
8713 APSR.Z = IsZeroBit(result);
8714 APSR.C = carry;
8715 APSR.V = overflow;
8716#endif
8717
8718 bool success = false;
8719 const uint32_t opcode = OpcodeAsUnsigned (&success);
8720 if (!success)
8721 return false;
8722
8723 uint32_t Rd; // the destination register
8724 uint32_t Rn; // the first operand
8725 uint32_t Rm; // the second operand
8726 bool setflags;
8727 ARM_ShifterType shift_t;
8728 uint32_t shift_n; // the shift applied to the value read from Rm
8729 switch (encoding) {
8730 case eEncodingA1:
8731 Rd = Bits32(opcode, 15, 12);
8732 Rn = Bits32(opcode, 19, 16);
8733 Rm = Bits32(opcode, 3, 0);
8734 setflags = BitIsSet(opcode, 20);
8735 shift_n = DecodeImmShiftARM(opcode, shift_t);
8736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8737 // TODO: Emulate SUBS PC, LR and related instructions.
8738 if (Rd == 15 && setflags)
8739 return false;
8740 break;
8741 default:
8742 return false;
8743 }
8744 // Read the register value from register Rn.
8745 uint32_t val1 = ReadCoreReg(Rn, &success);
8746 if (!success)
8747 return false;
8748
8749 // Read the register value from register Rm.
8750 uint32_t val2 = ReadCoreReg(Rm, &success);
8751 if (!success)
8752 return false;
8753
8754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8755 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8756
8757 EmulateInstruction::Context context;
8758 context.type = EmulateInstruction::eContextImmediate;
8759 context.SetNoArgs();
8760 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8761 return false;
8762
8763 return true;
8764}
8765
Johnny Chen9b381772011-02-23 01:01:21 +00008766// Subtract with Carry (immediate) subtracts an immediate value and the value of
8767// NOT (Carry flag) from a register value, and writes the result to the destination register.
8768// It can optionally update the condition flags based on the result.
8769bool
8770EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8771{
8772#if 0
8773 // ARM pseudo code...
8774 if ConditionPassed() then
8775 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008776 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008777 if d == 15 then // Can only occur for ARM encoding
8778 ALUWritePC(result); // setflags is always FALSE here
8779 else
8780 R[d] = result;
8781 if setflags then
8782 APSR.N = result<31>;
8783 APSR.Z = IsZeroBit(result);
8784 APSR.C = carry;
8785 APSR.V = overflow;
8786#endif
8787
8788 bool success = false;
8789 const uint32_t opcode = OpcodeAsUnsigned (&success);
8790 if (!success)
8791 return false;
8792
8793 uint32_t Rd; // the destination register
8794 uint32_t Rn; // the first operand
8795 bool setflags;
8796 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8797 switch (encoding) {
8798 case eEncodingT1:
8799 Rd = Bits32(opcode, 11, 8);
8800 Rn = Bits32(opcode, 19, 16);
8801 setflags = BitIsSet(opcode, 20);
8802 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8803 if (BadReg(Rd) || BadReg(Rn))
8804 return false;
8805 break;
8806 case eEncodingA1:
8807 Rd = Bits32(opcode, 15, 12);
8808 Rn = Bits32(opcode, 19, 16);
8809 setflags = BitIsSet(opcode, 20);
8810 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8811 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8812 // TODO: Emulate SUBS PC, LR and related instructions.
8813 if (Rd == 15 && setflags)
8814 return false;
8815 break;
8816 default:
8817 return false;
8818 }
8819 // Read the register value from the operand register Rn.
8820 uint32_t reg_val = ReadCoreReg(Rn, &success);
8821 if (!success)
8822 return false;
8823
8824 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8825
8826 EmulateInstruction::Context context;
8827 context.type = EmulateInstruction::eContextImmediate;
8828 context.SetNoArgs ();
8829
8830 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8831 return false;
8832
8833 return true;
8834}
8835
8836// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8837// NOT (Carry flag) from a register value, and writes the result to the destination register.
8838// It can optionally update the condition flags based on the result.
8839bool
8840EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8841{
8842#if 0
8843 // ARM pseudo code...
8844 if ConditionPassed() then
8845 EncodingSpecificOperations();
8846 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8847 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8848 if d == 15 then // Can only occur for ARM encoding
8849 ALUWritePC(result); // setflags is always FALSE here
8850 else
8851 R[d] = result;
8852 if setflags then
8853 APSR.N = result<31>;
8854 APSR.Z = IsZeroBit(result);
8855 APSR.C = carry;
8856 APSR.V = overflow;
8857#endif
8858
8859 bool success = false;
8860 const uint32_t opcode = OpcodeAsUnsigned (&success);
8861 if (!success)
8862 return false;
8863
8864 uint32_t Rd; // the destination register
8865 uint32_t Rn; // the first operand
8866 uint32_t Rm; // the second operand
8867 bool setflags;
8868 ARM_ShifterType shift_t;
8869 uint32_t shift_n; // the shift applied to the value read from Rm
8870 switch (encoding) {
8871 case eEncodingT1:
8872 Rd = Rn = Bits32(opcode, 2, 0);
8873 Rm = Bits32(opcode, 5, 3);
8874 setflags = !InITBlock();
8875 shift_t = SRType_LSL;
8876 shift_n = 0;
8877 break;
8878 case eEncodingT2:
8879 Rd = Bits32(opcode, 11, 8);
8880 Rn = Bits32(opcode, 19, 16);
8881 Rm = Bits32(opcode, 3, 0);
8882 setflags = BitIsSet(opcode, 20);
8883 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8884 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8885 return false;
8886 break;
8887 case eEncodingA1:
8888 Rd = Bits32(opcode, 15, 12);
8889 Rn = Bits32(opcode, 19, 16);
8890 Rm = Bits32(opcode, 3, 0);
8891 setflags = BitIsSet(opcode, 20);
8892 shift_n = DecodeImmShiftARM(opcode, shift_t);
8893 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8894 // TODO: Emulate SUBS PC, LR and related instructions.
8895 if (Rd == 15 && setflags)
8896 return false;
8897 break;
8898 default:
8899 return false;
8900 }
8901 // Read the register value from register Rn.
8902 uint32_t val1 = ReadCoreReg(Rn, &success);
8903 if (!success)
8904 return false;
8905
8906 // Read the register value from register Rm.
8907 uint32_t val2 = ReadCoreReg(Rm, &success);
8908 if (!success)
8909 return false;
8910
8911 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8912 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8913
8914 EmulateInstruction::Context context;
8915 context.type = EmulateInstruction::eContextImmediate;
8916 context.SetNoArgs();
8917 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8918 return false;
8919
8920 return true;
8921}
8922
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008923// This instruction subtracts an immediate value from a register value, and writes the result
8924// to the destination register. It can optionally update the condition flags based on the result.
8925bool
8926EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8927{
8928#if 0
8929 // ARM pseudo code...
8930 if ConditionPassed() then
8931 EncodingSpecificOperations();
8932 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8933 R[d] = result;
8934 if setflags then
8935 APSR.N = result<31>;
8936 APSR.Z = IsZeroBit(result);
8937 APSR.C = carry;
8938 APSR.V = overflow;
8939#endif
8940
8941 bool success = false;
8942 const uint32_t opcode = OpcodeAsUnsigned (&success);
8943 if (!success)
8944 return false;
8945
8946 uint32_t Rd; // the destination register
8947 uint32_t Rn; // the first operand
8948 bool setflags;
8949 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8950 switch (encoding) {
8951 case eEncodingT1:
8952 Rd = Bits32(opcode, 2, 0);
8953 Rn = Bits32(opcode, 5, 3);
8954 setflags = !InITBlock();
8955 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8956 break;
8957 case eEncodingT2:
8958 Rd = Rn = Bits32(opcode, 10, 8);
8959 setflags = !InITBlock();
8960 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8961 break;
8962 case eEncodingT3:
8963 Rd = Bits32(opcode, 11, 8);
8964 Rn = Bits32(opcode, 19, 16);
8965 setflags = BitIsSet(opcode, 20);
8966 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8967
8968 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8969 if (Rd == 15 && setflags)
8970 return EmulateCMPImm(eEncodingT2);
8971
8972 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8973 if (Rn == 13)
8974 return EmulateSUBSPImm(eEncodingT2);
8975
8976 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8977 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8978 return false;
8979 break;
8980 case eEncodingT4:
8981 Rd = Bits32(opcode, 11, 8);
8982 Rn = Bits32(opcode, 19, 16);
8983 setflags = BitIsSet(opcode, 20);
8984 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8985
8986 // if Rn == '1111' then SEE ADR;
8987 if (Rn == 15)
8988 return EmulateADR(eEncodingT2);
8989
8990 // if Rn == '1101' then SEE SUB (SP minus immediate);
8991 if (Rn == 13)
8992 return EmulateSUBSPImm(eEncodingT3);
8993
8994 if (BadReg(Rd))
8995 return false;
8996 break;
8997 default:
8998 return false;
8999 }
9000 // Read the register value from the operand register Rn.
9001 uint32_t reg_val = ReadCoreReg(Rn, &success);
9002 if (!success)
9003 return false;
9004
9005 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9006
9007 EmulateInstruction::Context context;
9008 context.type = EmulateInstruction::eContextImmediate;
9009 context.SetNoArgs ();
9010
9011 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9012 return false;
9013
9014 return true;
9015}
9016
9017// This instruction subtracts an immediate value from a register value, and writes the result
9018// to the destination register. It can optionally update the condition flags based on the result.
9019bool
9020EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
9021{
9022#if 0
9023 // ARM pseudo code...
9024 if ConditionPassed() then
9025 EncodingSpecificOperations();
9026 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9027 if d == 15 then
9028 ALUWritePC(result); // setflags is always FALSE here
9029 else
9030 R[d] = result;
9031 if setflags then
9032 APSR.N = result<31>;
9033 APSR.Z = IsZeroBit(result);
9034 APSR.C = carry;
9035 APSR.V = overflow;
9036#endif
9037
9038 bool success = false;
9039 const uint32_t opcode = OpcodeAsUnsigned (&success);
9040 if (!success)
9041 return false;
9042
9043 uint32_t Rd; // the destination register
9044 uint32_t Rn; // the first operand
9045 bool setflags;
9046 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9047 switch (encoding) {
9048 case eEncodingA1:
9049 Rd = Bits32(opcode, 15, 12);
9050 Rn = Bits32(opcode, 19, 16);
9051 setflags = BitIsSet(opcode, 20);
9052 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9053
9054 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
9055 if (Rn == 15 && !setflags)
9056 return EmulateADR(eEncodingA2);
9057
9058 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9059 if (Rn == 13)
9060 return EmulateSUBSPImm(eEncodingA1);
9061
9062 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9063 // TODO: Emulate SUBS PC, LR and related instructions.
9064 if (Rd == 15 && setflags)
9065 return false;
9066 break;
9067 default:
9068 return false;
9069 }
9070 // Read the register value from the operand register Rn.
9071 uint32_t reg_val = ReadCoreReg(Rn, &success);
9072 if (!success)
9073 return false;
9074
9075 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9076
9077 EmulateInstruction::Context context;
9078 context.type = EmulateInstruction::eContextImmediate;
9079 context.SetNoArgs ();
9080
9081 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9082 return false;
9083
9084 return true;
9085}
9086
Johnny Chen2115b412011-02-21 23:42:44 +00009087// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9088// immediate value. It updates the condition flags based on the result, and discards the result.
9089bool
9090EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
9091{
9092#if 0
9093 // ARM pseudo code...
9094 if ConditionPassed() then
9095 EncodingSpecificOperations();
9096 result = R[n] EOR imm32;
9097 APSR.N = result<31>;
9098 APSR.Z = IsZeroBit(result);
9099 APSR.C = carry;
9100 // APSR.V unchanged
9101#endif
9102
9103 bool success = false;
9104 const uint32_t opcode = OpcodeAsUnsigned (&success);
9105 if (!success)
9106 return false;
9107
9108 if (ConditionPassed())
9109 {
9110 uint32_t Rn;
9111 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9112 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9113 switch (encoding)
9114 {
9115 case eEncodingT1:
9116 Rn = Bits32(opcode, 19, 16);
9117 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9118 if (BadReg(Rn))
9119 return false;
9120 break;
9121 case eEncodingA1:
9122 Rn = Bits32(opcode, 19, 16);
9123 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9124 break;
9125 default:
9126 return false;
9127 }
9128
9129 // Read the first operand.
9130 uint32_t val1 = ReadCoreReg(Rn, &success);
9131 if (!success)
9132 return false;
9133
9134 uint32_t result = val1 ^ imm32;
9135
9136 EmulateInstruction::Context context;
9137 context.type = EmulateInstruction::eContextImmediate;
9138 context.SetNoArgs ();
9139
9140 if (!WriteFlags(context, result, carry))
9141 return false;
9142 }
9143 return true;
9144}
9145
9146// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9147// optionally-shifted register value. It updates the condition flags based on the result, and discards
9148// the result.
9149bool
9150EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
9151{
9152#if 0
9153 // ARM pseudo code...
9154 if ConditionPassed() then
9155 EncodingSpecificOperations();
9156 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9157 result = R[n] EOR shifted;
9158 APSR.N = result<31>;
9159 APSR.Z = IsZeroBit(result);
9160 APSR.C = carry;
9161 // APSR.V unchanged
9162#endif
9163
9164 bool success = false;
9165 const uint32_t opcode = OpcodeAsUnsigned (&success);
9166 if (!success)
9167 return false;
9168
9169 if (ConditionPassed())
9170 {
9171 uint32_t Rn, Rm;
9172 ARM_ShifterType shift_t;
9173 uint32_t shift_n; // the shift applied to the value read from Rm
9174 uint32_t carry;
9175 switch (encoding)
9176 {
9177 case eEncodingT1:
9178 Rn = Bits32(opcode, 19, 16);
9179 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009180 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009181 if (BadReg(Rn) || BadReg(Rm))
9182 return false;
9183 break;
9184 case eEncodingA1:
9185 Rn = Bits32(opcode, 19, 16);
9186 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009187 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009188 break;
9189 default:
9190 return false;
9191 }
9192
9193 // Read the first operand.
9194 uint32_t val1 = ReadCoreReg(Rn, &success);
9195 if (!success)
9196 return false;
9197
9198 // Read the second operand.
9199 uint32_t val2 = ReadCoreReg(Rm, &success);
9200 if (!success)
9201 return false;
9202
9203 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9204 uint32_t result = val1 ^ shifted;
9205
9206 EmulateInstruction::Context context;
9207 context.type = EmulateInstruction::eContextImmediate;
9208 context.SetNoArgs ();
9209
9210 if (!WriteFlags(context, result, carry))
9211 return false;
9212 }
9213 return true;
9214}
9215
Johnny Chende3cce32011-02-21 21:24:49 +00009216// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9217// It updates the condition flags based on the result, and discards the result.
9218bool
9219EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
9220{
9221#if 0
9222 // ARM pseudo code...
9223 if ConditionPassed() then
9224 EncodingSpecificOperations();
9225 result = R[n] AND imm32;
9226 APSR.N = result<31>;
9227 APSR.Z = IsZeroBit(result);
9228 APSR.C = carry;
9229 // APSR.V unchanged
9230#endif
9231
9232 bool success = false;
9233 const uint32_t opcode = OpcodeAsUnsigned (&success);
9234 if (!success)
9235 return false;
9236
9237 if (ConditionPassed())
9238 {
9239 uint32_t Rn;
9240 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9241 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9242 switch (encoding)
9243 {
9244 case eEncodingT1:
9245 Rn = Bits32(opcode, 19, 16);
9246 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9247 if (BadReg(Rn))
9248 return false;
9249 break;
9250 case eEncodingA1:
9251 Rn = Bits32(opcode, 19, 16);
9252 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9253 break;
9254 default:
9255 return false;
9256 }
9257
9258 // Read the first operand.
9259 uint32_t val1 = ReadCoreReg(Rn, &success);
9260 if (!success)
9261 return false;
9262
9263 uint32_t result = val1 & imm32;
9264
9265 EmulateInstruction::Context context;
9266 context.type = EmulateInstruction::eContextImmediate;
9267 context.SetNoArgs ();
9268
9269 if (!WriteFlags(context, result, carry))
9270 return false;
9271 }
9272 return true;
9273}
9274
9275// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9276// It updates the condition flags based on the result, and discards the result.
9277bool
9278EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9279{
9280#if 0
9281 // ARM pseudo code...
9282 if ConditionPassed() then
9283 EncodingSpecificOperations();
9284 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9285 result = R[n] AND shifted;
9286 APSR.N = result<31>;
9287 APSR.Z = IsZeroBit(result);
9288 APSR.C = carry;
9289 // APSR.V unchanged
9290#endif
9291
9292 bool success = false;
9293 const uint32_t opcode = OpcodeAsUnsigned (&success);
9294 if (!success)
9295 return false;
9296
9297 if (ConditionPassed())
9298 {
9299 uint32_t Rn, Rm;
9300 ARM_ShifterType shift_t;
9301 uint32_t shift_n; // the shift applied to the value read from Rm
9302 uint32_t carry;
9303 switch (encoding)
9304 {
9305 case eEncodingT1:
9306 Rn = Bits32(opcode, 2, 0);
9307 Rm = Bits32(opcode, 5, 3);
9308 shift_t = SRType_LSL;
9309 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009310 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009311 case eEncodingT2:
9312 Rn = Bits32(opcode, 19, 16);
9313 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009314 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009315 if (BadReg(Rn) || BadReg(Rm))
9316 return false;
9317 break;
9318 case eEncodingA1:
9319 Rn = Bits32(opcode, 19, 16);
9320 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009321 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009322 break;
9323 default:
9324 return false;
9325 }
9326
9327 // Read the first operand.
9328 uint32_t val1 = ReadCoreReg(Rn, &success);
9329 if (!success)
9330 return false;
9331
9332 // Read the second operand.
9333 uint32_t val2 = ReadCoreReg(Rm, &success);
9334 if (!success)
9335 return false;
9336
9337 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9338 uint32_t result = val1 & shifted;
9339
9340 EmulateInstruction::Context context;
9341 context.type = EmulateInstruction::eContextImmediate;
9342 context.SetNoArgs ();
9343
9344 if (!WriteFlags(context, result, carry))
9345 return false;
9346 }
9347 return true;
9348}
9349
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009350EmulateInstructionARM::ARMOpcode*
9351EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009352{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009353 static ARMOpcode
9354 g_arm_opcodes[] =
9355 {
9356 //----------------------------------------------------------------------
9357 // Prologue instructions
9358 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009359
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009360 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009361 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9362 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009363
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009364 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009365 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009366 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009367 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009368 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9369 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009370 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009371
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009372 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009373 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009374
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009375 // push one register
9376 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009377 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009378
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009379 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009380 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9381 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009382
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009383 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009384 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009385 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009386
Johnny Chen9f687722011-02-18 00:02:28 +00009387 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9388 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009389 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009390 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9391
9392 //----------------------------------------------------------------------
9393 // Supervisor Call (previously Software Interrupt)
9394 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009395 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9396
9397 //----------------------------------------------------------------------
9398 // Branch instructions
9399 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009400 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009401 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9402 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9403 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9404 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009405 // for example, "bx lr"
9406 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009407 // bxj
9408 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009409
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009410 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009411 // Data-processing instructions
9412 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009413 // adc (immediate)
9414 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9415 // adc (register)
9416 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009417 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009418 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009419 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009420 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009421 // adr
9422 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9423 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009424 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009425 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009426 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009427 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009428 // bic (immediate)
9429 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9430 // bic (register)
9431 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009432 // eor (immediate)
9433 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9434 // eor (register)
9435 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009436 // orr (immediate)
9437 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9438 // orr (register)
9439 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009440 // rsb (immediate)
9441 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9442 // rsb (register)
9443 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009444 // rsc (immediate)
9445 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9446 // rsc (register)
9447 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009448 // sbc (immediate)
9449 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9450 // sbc (register)
9451 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009452 // sub (immediate, ARM)
9453 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009454 // sub (sp minus immediate)
9455 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009456 // teq (immediate)
9457 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9458 // teq (register)
9459 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009460 // tst (immediate)
9461 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9462 // tst (register)
9463 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9464
9465
Johnny Chen01d61572011-02-25 00:23:25 +00009466 // mov (register)
9467 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009468 // mvn (immediate)
9469 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9470 // mvn (register)
9471 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009472 // cmn (immediate)
9473 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9474 // cmn (register)
9475 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009476 // cmp (immediate)
9477 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9478 // cmp (register)
9479 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009480 // asr (immediate)
9481 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009482 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009483 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009484 // lsl (immediate)
9485 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9486 // lsl (register)
9487 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9488 // lsr (immediate)
9489 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9490 // lsr (register)
9491 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009492 // rrx is a special case encoding of ror (immediate)
9493 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9494 // ror (immediate)
9495 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9496 // ror (register)
9497 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009498 // mul
9499 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009500
9501 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009502 // Load instructions
9503 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009504 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009505 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009506 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009507 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009508 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009509 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009510 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009511 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009512 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009513 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009514 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009515 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009516 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009517 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009518 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9519 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009520
9521 //----------------------------------------------------------------------
9522 // Store instructions
9523 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009524 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009525 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009526 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009527 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009528 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009529 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009530
Caroline Tice6bf65162011-03-03 17:42:58 +00009531 //----------------------------------------------------------------------
9532 // Other instructions
9533 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009534 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009535 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009536 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009537 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9538 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009539
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009540 };
9541 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9542
9543 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9544 {
9545 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9546 return &g_arm_opcodes[i];
9547 }
9548 return NULL;
9549}
Greg Clayton64c84432011-01-21 22:02:52 +00009550
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009551
9552EmulateInstructionARM::ARMOpcode*
9553EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009554{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009555
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009556 static ARMOpcode
9557 g_thumb_opcodes[] =
9558 {
9559 //----------------------------------------------------------------------
9560 // Prologue instructions
9561 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009562
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009563 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009564 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9565 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9566 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009567
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009568 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009569 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009570 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009571 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009572 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009573 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009574
Johnny Chen864a8e82011-02-18 00:07:39 +00009575 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009576 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009577
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009578 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009579 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009580 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009581 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9582 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009583
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009584 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009585 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9586 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009587
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009588 //----------------------------------------------------------------------
9589 // Epilogue instructions
9590 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009591
Caroline Ticee2212882011-03-22 22:38:28 +00009592 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009593 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009594 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9595 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9596 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009597 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9598 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009599
9600 //----------------------------------------------------------------------
9601 // Supervisor Call (previously Software Interrupt)
9602 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009603 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9604
9605 //----------------------------------------------------------------------
9606 // If Then makes up to four following instructions conditional.
9607 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009608 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9609
9610 //----------------------------------------------------------------------
9611 // Branch instructions
9612 //----------------------------------------------------------------------
9613 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9614 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +00009615 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009616 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009617 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009618 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009619 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009620 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009621 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009622 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009623 // for example, "bx lr"
9624 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009625 // bxj
9626 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009627 // compare and branch
9628 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009629 // table branch byte
9630 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9631 // table branch halfword
9632 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009633
9634 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009635 // Data-processing instructions
9636 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009637 // adc (immediate)
9638 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9639 // adc (register)
9640 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9641 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9642 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009643 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009644 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009645 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009646 // adr
9647 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9648 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9649 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009650 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009651 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009652 // and (register)
9653 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9654 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009655 // bic (immediate)
9656 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9657 // bic (register)
9658 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9659 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009660 // eor (immediate)
9661 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9662 // eor (register)
9663 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9664 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009665 // orr (immediate)
9666 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9667 // orr (register)
9668 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9669 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009670 // rsb (immediate)
9671 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9672 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9673 // rsb (register)
9674 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009675 // sbc (immediate)
9676 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9677 // sbc (register)
9678 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9679 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009680 // add (immediate, Thumb)
9681 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9682 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9683 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9684 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009685 // sub (immediate, Thumb)
9686 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9687 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9688 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9689 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009690 // sub (sp minus immediate)
9691 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9692 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009693 // teq (immediate)
9694 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9695 // teq (register)
9696 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009697 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009698 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009699 // tst (register)
9700 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9701 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9702
Johnny Chen7c5234d2011-02-18 23:41:11 +00009703
Johnny Chen338bf542011-02-10 19:29:03 +00009704 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009705 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009706 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009707 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009708 // mov{s}<c>.w <Rd>, <Rm>
9709 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009710 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009711 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9712 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009713 // mvn (immediate)
9714 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9715 // mvn (register)
9716 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9717 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009718 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009719 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009720 // cmn (register)
9721 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009722 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009723 // cmp (immediate)
9724 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009725 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009726 // cmp (register) (Rn and Rm both from r0-r7)
9727 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9728 // cmp (register) (Rn and Rm not both from r0-r7)
9729 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009730 // asr (immediate)
9731 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009732 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009733 // asr (register)
9734 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9735 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009736 // lsl (immediate)
9737 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9738 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9739 // lsl (register)
9740 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9741 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9742 // lsr (immediate)
9743 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9744 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9745 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009746 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009747 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009748 // rrx is a special case encoding of ror (immediate)
9749 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9750 // ror (immediate)
9751 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9752 // ror (register)
9753 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9754 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009755 // mul
9756 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9757 // mul
9758 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009759
Johnny Chen26863dc2011-02-09 23:43:29 +00009760 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009761 // Load instructions
9762 //----------------------------------------------------------------------
9763 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009764 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009765 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009766 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9767 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009768 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009769 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9770 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009771 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9772 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9773 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009774 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009775 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9776 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009777 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9778 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9779 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009780 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009781 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9782 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009783 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9784 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009785 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009786 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9787 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009788 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9789 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009790 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009791 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9792 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009793
9794 //----------------------------------------------------------------------
9795 // Store instructions
9796 //----------------------------------------------------------------------
9797 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009798 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009799 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009800 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9801 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9802 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9803 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9804 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9805 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9806 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9807 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009808 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009809 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9810 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009811
9812 //----------------------------------------------------------------------
9813 // Other instructions
9814 //----------------------------------------------------------------------
9815 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009816 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9817 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009818 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9819 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009820 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9821 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009822 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9823 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9824 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009825
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009826 };
9827
9828 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9829 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9830 {
9831 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9832 return &g_thumb_opcodes[i];
9833 }
9834 return NULL;
9835}
Greg Clayton64c84432011-01-21 22:02:52 +00009836
Greg Clayton31e2a382011-01-30 20:03:56 +00009837bool
Greg Clayton395fc332011-02-15 21:59:32 +00009838EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009839{
9840 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009841 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009842 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009843 {
Greg Clayton395fc332011-02-15 21:59:32 +00009844 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9845 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9846 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9847 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9848 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9849 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9850 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9851 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9852 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9853 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009854 }
9855 return m_arm_isa != 0;
9856}
9857
9858
Greg Clayton64c84432011-01-21 22:02:52 +00009859bool
9860EmulateInstructionARM::ReadInstruction ()
9861{
9862 bool success = false;
9863 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9864 if (success)
9865 {
9866 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9867 if (success)
9868 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009869 Context read_inst_context;
9870 read_inst_context.type = eContextReadOpcode;
9871 read_inst_context.SetNoArgs ();
9872
Greg Clayton64c84432011-01-21 22:02:52 +00009873 if (m_inst_cpsr & MASK_CPSR_T)
9874 {
9875 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009876 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009877
9878 if (success)
9879 {
9880 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9881 {
9882 m_inst.opcode_type = eOpcode16;
9883 m_inst.opcode.inst16 = thumb_opcode;
9884 }
9885 else
9886 {
9887 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009888 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009889 }
9890 }
9891 }
9892 else
9893 {
9894 m_inst_mode = eModeARM;
9895 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009896 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009897 }
9898 }
9899 }
9900 if (!success)
9901 {
9902 m_inst_mode = eModeInvalid;
9903 m_inst_pc = LLDB_INVALID_ADDRESS;
9904 }
9905 return success;
9906}
9907
Johnny Chenee9b1f72011-02-09 01:00:31 +00009908uint32_t
9909EmulateInstructionARM::ArchVersion ()
9910{
9911 return m_arm_isa;
9912}
9913
Greg Clayton64c84432011-01-21 22:02:52 +00009914bool
9915EmulateInstructionARM::ConditionPassed ()
9916{
9917 if (m_inst_cpsr == 0)
9918 return false;
9919
9920 const uint32_t cond = CurrentCond ();
9921
9922 if (cond == UINT32_MAX)
9923 return false;
9924
9925 bool result = false;
9926 switch (UnsignedBits(cond, 3, 1))
9927 {
9928 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9929 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9930 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9931 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9932 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9933 case 5:
9934 {
9935 bool n = (m_inst_cpsr & MASK_CPSR_N);
9936 bool v = (m_inst_cpsr & MASK_CPSR_V);
9937 result = n == v;
9938 }
9939 break;
9940 case 6:
9941 {
9942 bool n = (m_inst_cpsr & MASK_CPSR_N);
9943 bool v = (m_inst_cpsr & MASK_CPSR_V);
9944 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9945 }
9946 break;
9947 case 7:
9948 result = true;
9949 break;
9950 }
9951
9952 if (cond & 1)
9953 result = !result;
9954 return result;
9955}
9956
Johnny Chen9ee056b2011-02-08 00:06:35 +00009957uint32_t
9958EmulateInstructionARM::CurrentCond ()
9959{
9960 switch (m_inst_mode)
9961 {
9962 default:
9963 case eModeInvalid:
9964 break;
9965
9966 case eModeARM:
9967 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9968
9969 case eModeThumb:
9970 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9971 // 'cond' field of the encoding.
9972 if (m_inst.opcode_type == eOpcode16 &&
9973 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9974 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9975 {
9976 return Bits32(m_inst.opcode.inst16, 11, 7);
9977 }
9978 else if (m_inst.opcode_type == eOpcode32 &&
9979 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9980 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9981 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9982 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9983 {
9984 return Bits32(m_inst.opcode.inst32, 25, 22);
9985 }
9986
9987 return m_it_session.GetCond();
9988 }
9989 return UINT32_MAX; // Return invalid value
9990}
9991
Johnny Chen9ee056b2011-02-08 00:06:35 +00009992bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009993EmulateInstructionARM::InITBlock()
9994{
9995 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9996}
9997
9998bool
9999EmulateInstructionARM::LastInITBlock()
10000{
10001 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
10002}
10003
Caroline Ticeb27771d2011-03-03 22:37:46 +000010004bool
10005EmulateInstructionARM::BadMode (uint32_t mode)
10006{
10007
10008 switch (mode)
10009 {
10010 case 16: return false; // '10000'
10011 case 17: return false; // '10001'
10012 case 18: return false; // '10010'
10013 case 19: return false; // '10011'
10014 case 22: return false; // '10110'
10015 case 23: return false; // '10111'
10016 case 27: return false; // '11011'
10017 case 31: return false; // '11111'
10018 default: return true;
10019 }
10020 return true;
10021}
10022
10023bool
10024EmulateInstructionARM::CurrentModeIsPrivileged ()
10025{
10026 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
10027
10028 if (BadMode (mode))
10029 return false;
10030
10031 if (mode == 16)
10032 return false;
10033
10034 return true;
10035}
10036
10037void
10038EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
10039{
10040 bool privileged = CurrentModeIsPrivileged();
10041
10042 uint32_t tmp_cpsr = 0;
10043
10044 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
10045
10046 if (BitIsSet (bytemask, 3))
10047 {
10048 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10049 if (affect_execstate)
10050 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10051 }
10052
10053 if (BitIsSet (bytemask, 2))
10054 {
10055 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10056 }
10057
10058 if (BitIsSet (bytemask, 1))
10059 {
10060 if (affect_execstate)
10061 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10062 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10063 if (privileged)
10064 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10065 }
10066
10067 if (BitIsSet (bytemask, 0))
10068 {
10069 if (privileged)
10070 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10071 if (affect_execstate)
10072 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10073 if (privileged)
10074 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10075 }
10076
10077 m_inst_cpsr = tmp_cpsr;
10078}
10079
10080
Johnny Chen098ae2d2011-02-12 00:50:05 +000010081bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000010082EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
10083{
10084 addr_t target;
10085
Johnny Chenee9b1f72011-02-09 01:00:31 +000010086 // Check the current instruction set.
10087 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010088 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010089 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000010090 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010091
Johnny Chen9ee056b2011-02-08 00:06:35 +000010092 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010093 return false;
10094
10095 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010096}
10097
10098// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
10099bool
Johnny Chen668b4512011-02-15 21:08:58 +000010100EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010101{
10102 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000010103 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
10104 // we want to record it and issue a WriteRegister callback so the clients
10105 // can track the mode changes accordingly.
10106 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010107
10108 if (BitIsSet(addr, 0))
10109 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010110 if (CurrentInstrSet() != eModeThumb)
10111 {
10112 SelectInstrSet(eModeThumb);
10113 cpsr_changed = true;
10114 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010115 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000010116 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010117 }
10118 else if (BitIsClear(addr, 1))
10119 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010120 if (CurrentInstrSet() != eModeARM)
10121 {
10122 SelectInstrSet(eModeARM);
10123 cpsr_changed = true;
10124 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010125 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000010126 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010127 }
10128 else
10129 return false; // address<1:0> == '10' => UNPREDICTABLE
10130
Johnny Chen0f309db2011-02-09 19:11:32 +000010131 if (cpsr_changed)
10132 {
Johnny Chen558133b2011-02-09 23:59:17 +000010133 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000010134 return false;
10135 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010136 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010137 return false;
10138
10139 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010140}
Greg Clayton64c84432011-01-21 22:02:52 +000010141
Johnny Chenee9b1f72011-02-09 01:00:31 +000010142// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10143bool
Johnny Chen668b4512011-02-15 21:08:58 +000010144EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000010145{
10146 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000010147 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000010148 else
10149 return BranchWritePC((const Context)context, addr);
10150}
10151
Johnny Chen26863dc2011-02-09 23:43:29 +000010152// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
10153bool
Johnny Chen668b4512011-02-15 21:08:58 +000010154EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000010155{
10156 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000010157 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000010158 else
10159 return BranchWritePC((const Context)context, addr);
10160}
10161
Johnny Chenee9b1f72011-02-09 01:00:31 +000010162EmulateInstructionARM::Mode
10163EmulateInstructionARM::CurrentInstrSet ()
10164{
10165 return m_inst_mode;
10166}
10167
10168// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010169// ReadInstruction() is performed. This function has a side effect of updating
10170// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010171bool
10172EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10173{
Johnny Chen558133b2011-02-09 23:59:17 +000010174 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010175 switch (arm_or_thumb)
10176 {
10177 default:
10178 return false;
10179 eModeARM:
10180 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010181 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010182 break;
10183 eModeThumb:
10184 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010185 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010186 break;
10187 }
10188 return true;
10189}
10190
Johnny Chenef21b592011-02-10 01:52:38 +000010191// This function returns TRUE if the processor currently provides support for
10192// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10193// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10194bool
10195EmulateInstructionARM::UnalignedSupport()
10196{
10197 return (ArchVersion() >= ARMv7);
10198}
10199
Johnny Chenbf6ad172011-02-11 01:29:53 +000010200// The main addition and subtraction instructions can produce status information
10201// about both unsigned carry and signed overflow conditions. This status
10202// information can be used to synthesize multi-word additions and subtractions.
10203EmulateInstructionARM::AddWithCarryResult
10204EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10205{
10206 uint32_t result;
10207 uint8_t carry_out;
10208 uint8_t overflow;
10209
10210 uint64_t unsigned_sum = x + y + carry_in;
10211 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10212
10213 result = UnsignedBits(unsigned_sum, 31, 0);
10214 carry_out = (result == unsigned_sum ? 0 : 1);
10215 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10216
10217 AddWithCarryResult res = { result, carry_out, overflow };
10218 return res;
10219}
10220
Johnny Chen157b9592011-02-18 21:13:05 +000010221uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010222EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010223{
Johnny Chene39f22d2011-02-19 01:36:13 +000010224 uint32_t reg_kind, reg_num;
10225 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010226 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010227 case SP_REG:
10228 reg_kind = eRegisterKindGeneric;
10229 reg_num = LLDB_REGNUM_GENERIC_SP;
10230 break;
10231 case LR_REG:
10232 reg_kind = eRegisterKindGeneric;
10233 reg_num = LLDB_REGNUM_GENERIC_RA;
10234 break;
10235 case PC_REG:
10236 reg_kind = eRegisterKindGeneric;
10237 reg_num = LLDB_REGNUM_GENERIC_PC;
10238 break;
10239 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010240 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010241 {
10242 reg_kind = eRegisterKindDWARF;
10243 reg_num = dwarf_r0 + num;
10244 }
Johnny Chen157b9592011-02-18 21:13:05 +000010245 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010246 {
10247 assert(0 && "Invalid register number");
10248 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010249 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010250 }
10251 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010252 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010253
10254 // Read our register.
10255 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10256
10257 // When executing an ARM instruction , PC reads as the address of the current
10258 // instruction plus 8.
10259 // When executing a Thumb instruction , PC reads as the address of the current
10260 // instruction plus 4.
10261 if (num == 15)
10262 {
10263 if (CurrentInstrSet() == eModeARM)
10264 val += 8;
10265 else
10266 val += 4;
10267 }
Johnny Chen157b9592011-02-18 21:13:05 +000010268
10269 return val;
10270}
10271
Johnny Chenca67d1c2011-02-17 01:35:27 +000010272// Write the result to the ARM core register Rd, and optionally update the
10273// condition flags based on the result.
10274//
10275// This helper method tries to encapsulate the following pseudocode from the
10276// ARM Architecture Reference Manual:
10277//
10278// if d == 15 then // Can only occur for encoding A1
10279// ALUWritePC(result); // setflags is always FALSE here
10280// else
10281// R[d] = result;
10282// if setflags then
10283// APSR.N = result<31>;
10284// APSR.Z = IsZeroBit(result);
10285// APSR.C = carry;
10286// // APSR.V unchanged
10287//
10288// In the above case, the API client does not pass in the overflow arg, which
10289// defaults to ~0u.
10290bool
Johnny Chen10530c22011-02-17 22:37:12 +000010291EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10292 const uint32_t result,
10293 const uint32_t Rd,
10294 bool setflags,
10295 const uint32_t carry,
10296 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010297{
10298 if (Rd == 15)
10299 {
10300 if (!ALUWritePC (context, result))
10301 return false;
10302 }
10303 else
10304 {
Johnny Chena695f952011-02-23 21:24:25 +000010305 uint32_t reg_kind, reg_num;
10306 switch (Rd)
10307 {
10308 case SP_REG:
10309 reg_kind = eRegisterKindGeneric;
10310 reg_num = LLDB_REGNUM_GENERIC_SP;
10311 break;
10312 case LR_REG:
10313 reg_kind = eRegisterKindGeneric;
10314 reg_num = LLDB_REGNUM_GENERIC_RA;
10315 break;
10316 default:
10317 reg_kind = eRegisterKindDWARF;
10318 reg_num = dwarf_r0 + Rd;
10319 }
10320 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010321 return false;
10322 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010323 return WriteFlags (context, result, carry, overflow);
10324 }
10325 return true;
10326}
10327
10328// This helper method tries to encapsulate the following pseudocode from the
10329// ARM Architecture Reference Manual:
10330//
10331// APSR.N = result<31>;
10332// APSR.Z = IsZeroBit(result);
10333// APSR.C = carry;
10334// APSR.V = overflow
10335//
10336// Default arguments can be specified for carry and overflow parameters, which means
10337// not to update the respective flags.
10338bool
10339EmulateInstructionARM::WriteFlags (Context &context,
10340 const uint32_t result,
10341 const uint32_t carry,
10342 const uint32_t overflow)
10343{
10344 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010345 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10346 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010347 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010348 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010349 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010350 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010351 if (m_new_inst_cpsr != m_inst_cpsr)
10352 {
10353 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10354 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010355 }
10356 return true;
10357}
10358
Greg Clayton64c84432011-01-21 22:02:52 +000010359bool
10360EmulateInstructionARM::EvaluateInstruction ()
10361{
Johnny Chenc315f862011-02-05 00:46:10 +000010362 // Advance the ITSTATE bits to their values for the next instruction.
10363 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10364 m_it_session.ITAdvance();
10365
Greg Clayton64c84432011-01-21 22:02:52 +000010366 return false;
10367}