blob: dd9e06626bf5658df0c8beebd517b275ede3df3a [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) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003764 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
3773 break;
3774
3775 case eEncodingT2:
3776 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3777 Rt = Bits32 (opcode, 10, 8);
3778 Rn = 13;
3779 imm32 = Bits32 (opcode, 7, 0) << 2;
3780
3781 // index = TRUE; add = TRUE; wback = FALSE;
3782 index = true;
3783 add = true;
3784 wback = false;
3785
3786 break;
3787
3788 case eEncodingT3:
3789 // if Rn == ‘1111’ then SEE LDR (literal);
3790 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3791 Rt = Bits32 (opcode, 15, 12);
3792 Rn = Bits32 (opcode, 19, 16);
3793 imm32 = Bits32 (opcode, 11, 0);
3794
3795 // index = TRUE; add = TRUE; wback = FALSE;
3796 index = true;
3797 add = true;
3798 wback = false;
3799
3800 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3801 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3802 return false;
3803
3804 break;
3805
3806 case eEncodingT4:
3807 // if Rn == ‘1111’ then SEE LDR (literal);
3808 // if P == ‘1’ && U == ‘1’ && W == ‘0’ then SEE LDRT;
3809 // if Rn == ‘1101’ && P == ‘0’ && U == ‘1’ && W == ‘1’ && imm8 == ‘00000100’ then SEE POP;
3810 // if P == ‘0’ && W == ‘0’ then UNDEFINED;
3811 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3812 return false;
3813
3814 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3815 Rt = Bits32 (opcode, 15, 12);
3816 Rn = Bits32 (opcode, 19, 16);
3817 imm32 = Bits32 (opcode, 7, 0);
3818
3819 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
3820 index = BitIsSet (opcode, 10);
3821 add = BitIsSet (opcode, 9);
3822 wback = BitIsSet (opcode, 8);
3823
3824 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3825 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3826 return false;
3827
3828 break;
3829
3830 default:
3831 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003832 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003833 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003834 if (!success)
3835 return false;
3836 if (add)
3837 offset_addr = base + imm32;
3838 else
3839 offset_addr = base - imm32;
3840
3841 address = (index ? offset_addr : base);
3842
Caroline Ticebaf1f642011-03-24 19:23:45 +00003843 Register base_reg;
3844 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003845 if (wback)
3846 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003847 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003848 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3849 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003850
Johnny Chenef21b592011-02-10 01:52:38 +00003851 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3852 return false;
3853 }
3854
3855 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003856 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003857 context.type = EmulateInstruction::eContextRegisterLoad;
3858 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003859
3860 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003861 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003862 if (!success)
3863 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003864
3865 if (Rt == 15)
3866 {
3867 if (Bits32(address, 1, 0) == 0)
3868 {
Johnny Chen668b4512011-02-15 21:08:58 +00003869 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003870 return false;
3871 }
3872 else
3873 return false;
3874 }
3875 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3876 {
3877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3878 return false;
3879 }
3880 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003881 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003882 }
3883 return true;
3884}
3885
Caroline Ticeaf556562011-02-15 18:42:15 +00003886// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3887// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3888// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003889bool
3890EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3891{
3892#if 0
3893 if ConditionPassed() then
3894 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3895 address = R[n];
3896
3897 for i = 0 to 14
3898 if registers<i> == ’1’ then
3899 if i == n && wback && i != LowestSetBit(registers) then
3900 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3901 else
3902 MemA[address,4] = R[i];
3903 address = address + 4;
3904
3905 if registers<15> == ’1’ then // Only possible for encoding A1
3906 MemA[address,4] = PCStoreValue();
3907 if wback then R[n] = R[n] + 4*BitCount(registers);
3908#endif
3909
3910 bool success = false;
3911 const uint32_t opcode = OpcodeAsUnsigned (&success);
3912 if (!success)
3913 return false;
3914
3915 if (ConditionPassed ())
3916 {
3917 uint32_t n;
3918 uint32_t registers = 0;
3919 bool wback;
3920 const uint32_t addr_byte_size = GetAddressByteSize();
3921
3922 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3923 switch (encoding)
3924 {
3925 case eEncodingT1:
3926 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3927 n = Bits32 (opcode, 10, 8);
3928 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003929 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003930 wback = true;
3931
3932 // if BitCount(registers) < 1 then UNPREDICTABLE;
3933 if (BitCount (registers) < 1)
3934 return false;
3935
3936 break;
3937
3938 case eEncodingT2:
3939 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3940 n = Bits32 (opcode, 19, 16);
3941 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003942 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003943 wback = BitIsSet (opcode, 21);
3944
3945 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3946 if ((n == 15) || (BitCount (registers) < 2))
3947 return false;
3948
3949 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3950 if (wback && BitIsSet (registers, n))
3951 return false;
3952
3953 break;
3954
3955 case eEncodingA1:
3956 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3957 n = Bits32 (opcode, 19, 16);
3958 registers = Bits32 (opcode, 15, 0);
3959 wback = BitIsSet (opcode, 21);
3960
3961 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3962 if ((n == 15) || (BitCount (registers) < 1))
3963 return false;
3964
3965 break;
3966
3967 default:
3968 return false;
3969 }
3970
3971 // address = R[n];
3972 int32_t offset = 0;
3973 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3974 if (!success)
3975 return false;
3976
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003977 EmulateInstruction::Context context;
3978 context.type = EmulateInstruction::eContextRegisterStore;
3979 Register base_reg;
3980 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003981
3982 // for i = 0 to 14
3983 for (int i = 0; i < 14; ++i)
3984 {
3985 int lowest_set_bit = 14;
3986 // if registers<i> == ’1’ then
3987 if (BitIsSet (registers, i))
3988 {
3989 if (i < lowest_set_bit)
3990 lowest_set_bit = i;
3991 // if i == n && wback && i != LowestSetBit(registers) then
3992 if ((i == n) && wback && (i != lowest_set_bit))
3993 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3994 WriteBits32UnknownToMemory (address + offset);
3995 else
3996 {
3997 // MemA[address,4] = R[i];
3998 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3999 if (!success)
4000 return false;
4001
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004002 Register data_reg;
4003 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4004 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004005 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004006 return false;
4007 }
4008
4009 // address = address + 4;
4010 offset += addr_byte_size;
4011 }
4012 }
4013
4014 // if registers<15> == ’1’ then // Only possible for encoding A1
4015 // MemA[address,4] = PCStoreValue();
4016 if (BitIsSet (registers, 15))
4017 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004018 Register pc_reg;
4019 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4020 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004021 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004022 if (!success)
4023 return false;
4024
Caroline Tice8d681f52011-03-17 23:50:16 +00004025 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004026 return false;
4027 }
4028
4029 // if wback then R[n] = R[n] + 4*BitCount(registers);
4030 if (wback)
4031 {
4032 offset = addr_byte_size * BitCount (registers);
4033 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004034 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004035 addr_t data = address + offset;
4036 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4037 return false;
4038 }
4039 }
4040 return true;
4041}
4042
Caroline Ticeaf556562011-02-15 18:42:15 +00004043// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4044// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4045// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004046bool
4047EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
4048{
4049#if 0
4050 if ConditionPassed() then
4051 EncodingSpecificOperations();
4052 address = R[n] - 4*BitCount(registers) + 4;
4053
4054 for i = 0 to 14
4055 if registers<i> == ’1’ then
4056 if i == n && wback && i != LowestSetBit(registers) then
4057 MemA[address,4] = bits(32) UNKNOWN;
4058 else
4059 MemA[address,4] = R[i];
4060 address = address + 4;
4061
4062 if registers<15> == ’1’ then
4063 MemA[address,4] = PCStoreValue();
4064
4065 if wback then R[n] = R[n] - 4*BitCount(registers);
4066#endif
4067
4068 bool success = false;
4069 const uint32_t opcode = OpcodeAsUnsigned (&success);
4070 if (!success)
4071 return false;
4072
4073 if (ConditionPassed ())
4074 {
4075 uint32_t n;
4076 uint32_t registers = 0;
4077 bool wback;
4078 const uint32_t addr_byte_size = GetAddressByteSize();
4079
4080 // EncodingSpecificOperations();
4081 switch (encoding)
4082 {
4083 case eEncodingA1:
4084 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4085 n = Bits32 (opcode, 19, 16);
4086 registers = Bits32 (opcode, 15, 0);
4087 wback = BitIsSet (opcode, 21);
4088
4089 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4090 if ((n == 15) || (BitCount (registers) < 1))
4091 return false;
4092 break;
4093 default:
4094 return false;
4095 }
4096
4097 // address = R[n] - 4*BitCount(registers) + 4;
4098 int32_t offset = 0;
4099 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4100 if (!success)
4101 return false;
4102
4103 address = address - (addr_byte_size * BitCount (registers)) + 4;
4104
4105 EmulateInstruction::Context context;
4106 context.type = EmulateInstruction::eContextRegisterStore;
4107 Register base_reg;
4108 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4109
4110 // for i = 0 to 14
4111 for (int i = 0; i < 14; ++i)
4112 {
4113 int lowest_bit_set = 14;
4114 // if registers<i> == ’1’ then
4115 if (BitIsSet (registers, i))
4116 {
4117 if (i < lowest_bit_set)
4118 lowest_bit_set = i;
4119 //if i == n && wback && i != LowestSetBit(registers) then
4120 if ((i == n) && wback && (i != lowest_bit_set))
4121 // MemA[address,4] = bits(32) UNKNOWN;
4122 WriteBits32UnknownToMemory (address + offset);
4123 else
4124 {
4125 // MemA[address,4] = R[i];
4126 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4127 if (!success)
4128 return false;
4129
4130 Register data_reg;
4131 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4132 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004133 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004134 return false;
4135 }
4136
4137 // address = address + 4;
4138 offset += addr_byte_size;
4139 }
4140 }
4141
4142 // if registers<15> == ’1’ then
4143 // MemA[address,4] = PCStoreValue();
4144 if (BitIsSet (registers, 15))
4145 {
4146 Register pc_reg;
4147 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4148 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004149 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004150 if (!success)
4151 return false;
4152
Caroline Tice8d681f52011-03-17 23:50:16 +00004153 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004154 return false;
4155 }
4156
4157 // if wback then R[n] = R[n] - 4*BitCount(registers);
4158 if (wback)
4159 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004160 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004161 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4162 context.SetImmediateSigned (offset);
4163 addr_t data = address + offset;
4164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4165 return false;
4166 }
4167 }
4168 return true;
4169}
4170
Caroline Ticeaf556562011-02-15 18:42:15 +00004171// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4172// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4173// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004174bool
4175EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4176{
4177#if 0
4178 if ConditionPassed() then
4179 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4180 address = R[n] - 4*BitCount(registers);
4181
4182 for i = 0 to 14
4183 if registers<i> == ’1’ then
4184 if i == n && wback && i != LowestSetBit(registers) then
4185 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4186 else
4187 MemA[address,4] = R[i];
4188 address = address + 4;
4189
4190 if registers<15> == ’1’ then // Only possible for encoding A1
4191 MemA[address,4] = PCStoreValue();
4192
4193 if wback then R[n] = R[n] - 4*BitCount(registers);
4194#endif
4195
4196
4197 bool success = false;
4198 const uint32_t opcode = OpcodeAsUnsigned (&success);
4199 if (!success)
4200 return false;
4201
4202 if (ConditionPassed ())
4203 {
4204 uint32_t n;
4205 uint32_t registers = 0;
4206 bool wback;
4207 const uint32_t addr_byte_size = GetAddressByteSize();
4208
4209 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4210 switch (encoding)
4211 {
4212 case eEncodingT1:
4213 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4214 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4215 {
4216 // See PUSH
4217 }
4218 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4219 n = Bits32 (opcode, 19, 16);
4220 registers = Bits32 (opcode, 15, 0);
4221 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4222 wback = BitIsSet (opcode, 21);
4223 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4224 if ((n == 15) || BitCount (registers) < 2)
4225 return false;
4226 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4227 if (wback && BitIsSet (registers, n))
4228 return false;
4229 break;
4230
4231 case eEncodingA1:
4232 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4233 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4234 {
4235 // See Push
4236 }
4237 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4238 n = Bits32 (opcode, 19, 16);
4239 registers = Bits32 (opcode, 15, 0);
4240 wback = BitIsSet (opcode, 21);
4241 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4242 if ((n == 15) || BitCount (registers) < 1)
4243 return false;
4244 break;
4245
4246 default:
4247 return false;
4248 }
4249
4250 // address = R[n] - 4*BitCount(registers);
4251
4252 int32_t offset = 0;
4253 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4254 if (!success)
4255 return false;
4256
4257 address = address - (addr_byte_size * BitCount (registers));
4258
4259 EmulateInstruction::Context context;
4260 context.type = EmulateInstruction::eContextRegisterStore;
4261 Register base_reg;
4262 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4263
4264 // for i = 0 to 14
4265 for (int i = 0; i < 14; ++i)
4266 {
4267 uint32_t lowest_set_bit = 14;
4268 // if registers<i> == ’1’ then
4269 if (BitIsSet (registers, i))
4270 {
4271 if (i < lowest_set_bit)
4272 lowest_set_bit = i;
4273 // if i == n && wback && i != LowestSetBit(registers) then
4274 if ((i == n) && wback && (i != lowest_set_bit))
4275 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4276 WriteBits32UnknownToMemory (address + offset);
4277 else
4278 {
4279 // MemA[address,4] = R[i];
4280 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4281 if (!success)
4282 return false;
4283
4284 Register data_reg;
4285 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4286 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004287 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004288 return false;
4289 }
4290
4291 // address = address + 4;
4292 offset += addr_byte_size;
4293 }
4294 }
4295
4296 // if registers<15> == ’1’ then // Only possible for encoding A1
4297 // MemA[address,4] = PCStoreValue();
4298 if (BitIsSet (registers, 15))
4299 {
4300 Register pc_reg;
4301 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4302 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004303 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004304 if (!success)
4305 return false;
4306
Caroline Tice8d681f52011-03-17 23:50:16 +00004307 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004308 return false;
4309 }
4310
4311 // if wback then R[n] = R[n] - 4*BitCount(registers);
4312 if (wback)
4313 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004314 offset = (addr_byte_size * BitCount (registers)) * -1;
4315 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4316 context.SetImmediateSigned (offset);
4317 addr_t data = address + offset;
4318 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4319 return false;
4320 }
4321 }
4322 return true;
4323}
4324
4325// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4326// from a base register. The consecutive memory locations start just above this address, and the address of the last
4327// of those locations can optionally be written back to the base register.
4328bool
4329EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4330{
4331#if 0
4332 if ConditionPassed() then
4333 EncodingSpecificOperations();
4334 address = R[n] + 4;
4335
4336 for i = 0 to 14
4337 if registers<i> == ’1’ then
4338 if i == n && wback && i != LowestSetBit(registers) then
4339 MemA[address,4] = bits(32) UNKNOWN;
4340 else
4341 MemA[address,4] = R[i];
4342 address = address + 4;
4343
4344 if registers<15> == ’1’ then
4345 MemA[address,4] = PCStoreValue();
4346
4347 if wback then R[n] = R[n] + 4*BitCount(registers);
4348#endif
4349
4350 bool success = false;
4351 const uint32_t opcode = OpcodeAsUnsigned (&success);
4352 if (!success)
4353 return false;
4354
4355 if (ConditionPassed())
4356 {
4357 uint32_t n;
4358 uint32_t registers = 0;
4359 bool wback;
4360 const uint32_t addr_byte_size = GetAddressByteSize();
4361
4362 // EncodingSpecificOperations();
4363 switch (encoding)
4364 {
4365 case eEncodingA1:
4366 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4367 n = Bits32 (opcode, 19, 16);
4368 registers = Bits32 (opcode, 15, 0);
4369 wback = BitIsSet (opcode, 21);
4370
4371 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4372 if ((n == 15) && (BitCount (registers) < 1))
4373 return false;
4374 break;
4375 default:
4376 return false;
4377 }
4378 // address = R[n] + 4;
4379
4380 int32_t offset = 0;
4381 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4382 if (!success)
4383 return false;
4384
4385 address = address + addr_byte_size;
4386
4387 EmulateInstruction::Context context;
4388 context.type = EmulateInstruction::eContextRegisterStore;
4389 Register base_reg;
4390 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4391
4392 uint32_t lowest_set_bit = 14;
4393 // for i = 0 to 14
4394 for (int i = 0; i < 14; ++i)
4395 {
4396 // if registers<i> == ’1’ then
4397 if (BitIsSet (registers, i))
4398 {
4399 if (i < lowest_set_bit)
4400 lowest_set_bit = i;
4401 // if i == n && wback && i != LowestSetBit(registers) then
4402 if ((i == n) && wback && (i != lowest_set_bit))
4403 // MemA[address,4] = bits(32) UNKNOWN;
4404 WriteBits32UnknownToMemory (address + offset);
4405 // else
4406 else
4407 {
4408 // MemA[address,4] = R[i];
4409 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4410 if (!success)
4411 return false;
4412
4413 Register data_reg;
4414 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4415 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004416 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004417 return false;
4418 }
4419
4420 // address = address + 4;
4421 offset += addr_byte_size;
4422 }
4423 }
4424
4425 // if registers<15> == ’1’ then
4426 // MemA[address,4] = PCStoreValue();
4427 if (BitIsSet (registers, 15))
4428 {
4429 Register pc_reg;
4430 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4431 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004432 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004433 if (!success)
4434 return false;
4435
Caroline Tice8d681f52011-03-17 23:50:16 +00004436 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004437 return false;
4438 }
4439
4440 // if wback then R[n] = R[n] + 4*BitCount(registers);
4441 if (wback)
4442 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004443 offset = addr_byte_size * BitCount (registers);
4444 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4445 context.SetImmediateSigned (offset);
4446 addr_t data = address + offset;
4447 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4448 return false;
4449 }
4450 }
4451 return true;
4452}
Caroline Tice7fac8572011-02-15 22:53:54 +00004453
4454// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4455// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4456bool
4457EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4458{
4459#if 0
4460 if ConditionPassed() then
4461 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4462 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4463 address = if index then offset_addr else R[n];
4464 if UnalignedSupport() || address<1:0> == ’00’ then
4465 MemU[address,4] = R[t];
4466 else // Can only occur before ARMv7
4467 MemU[address,4] = bits(32) UNKNOWN;
4468 if wback then R[n] = offset_addr;
4469#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004470
Caroline Tice7fac8572011-02-15 22:53:54 +00004471 bool success = false;
4472 const uint32_t opcode = OpcodeAsUnsigned (&success);
4473 if (!success)
4474 return false;
4475
4476 if (ConditionPassed())
4477 {
4478 const uint32_t addr_byte_size = GetAddressByteSize();
4479
4480 uint32_t t;
4481 uint32_t n;
4482 uint32_t imm32;
4483 bool index;
4484 bool add;
4485 bool wback;
4486 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4487 switch (encoding)
4488 {
4489 case eEncodingT1:
4490 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4491 t = Bits32 (opcode, 2, 0);
4492 n = Bits32 (opcode, 5, 3);
4493 imm32 = Bits32 (opcode, 10, 6) << 2;
4494
4495 // index = TRUE; add = TRUE; wback = FALSE;
4496 index = true;
4497 add = false;
4498 wback = false;
4499 break;
4500
4501 case eEncodingT2:
4502 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4503 t = Bits32 (opcode, 10, 8);
4504 n = 13;
4505 imm32 = Bits32 (opcode, 7, 0) << 2;
4506
4507 // index = TRUE; add = TRUE; wback = FALSE;
4508 index = true;
4509 add = true;
4510 wback = false;
4511 break;
4512
4513 case eEncodingT3:
4514 // if Rn == ’1111’ then UNDEFINED;
4515 if (Bits32 (opcode, 19, 16) == 15)
4516 return false;
4517
4518 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4519 t = Bits32 (opcode, 15, 12);
4520 n = Bits32 (opcode, 19, 16);
4521 imm32 = Bits32 (opcode, 11, 0);
4522
4523 // index = TRUE; add = TRUE; wback = FALSE;
4524 index = true;
4525 add = true;
4526 wback = false;
4527
4528 // if t == 15 then UNPREDICTABLE;
4529 if (t == 15)
4530 return false;
4531 break;
4532
4533 case eEncodingT4:
4534 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4535 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4536 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4537 if ((Bits32 (opcode, 19, 16) == 15)
4538 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4539 return false;
4540
4541 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4542 t = Bits32 (opcode, 15, 12);
4543 n = Bits32 (opcode, 19, 16);
4544 imm32 = Bits32 (opcode, 7, 0);
4545
4546 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4547 index = BitIsSet (opcode, 10);
4548 add = BitIsSet (opcode, 9);
4549 wback = BitIsSet (opcode, 8);
4550
4551 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4552 if ((t == 15) || (wback && (n == t)))
4553 return false;
4554 break;
4555
4556 default:
4557 return false;
4558 }
4559
4560 addr_t offset_addr;
4561 addr_t address;
4562
4563 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004564 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004565 if (!success)
4566 return false;
4567
4568 if (add)
4569 offset_addr = base_address + imm32;
4570 else
4571 offset_addr = base_address - imm32;
4572
4573 // address = if index then offset_addr else R[n];
4574 if (index)
4575 address = offset_addr;
4576 else
4577 address = base_address;
4578
4579 EmulateInstruction::Context context;
4580 context.type = eContextRegisterStore;
4581 Register base_reg;
4582 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4583
4584 // if UnalignedSupport() || address<1:0> == ’00’ then
4585 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4586 {
4587 // MemU[address,4] = R[t];
4588 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4589 if (!success)
4590 return false;
4591
4592 Register data_reg;
4593 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4594 int32_t offset = address - base_address;
4595 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004596 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004597 return false;
4598 }
4599 else
4600 {
4601 // MemU[address,4] = bits(32) UNKNOWN;
4602 WriteBits32UnknownToMemory (address);
4603 }
4604
4605 // if wback then R[n] = offset_addr;
4606 if (wback)
4607 {
4608 context.type = eContextRegisterLoad;
4609 context.SetAddress (offset_addr);
4610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4611 return false;
4612 }
4613 }
4614 return true;
4615}
Caroline Ticeaf556562011-02-15 18:42:15 +00004616
Caroline Tice3fd63e92011-02-16 00:33:43 +00004617// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4618// word from a register to memory. The offset register value can optionally be shifted.
4619bool
4620EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4621{
4622#if 0
4623 if ConditionPassed() then
4624 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4625 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4626 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4627 address = if index then offset_addr else R[n];
4628 if t == 15 then // Only possible for encoding A1
4629 data = PCStoreValue();
4630 else
4631 data = R[t];
4632 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4633 MemU[address,4] = data;
4634 else // Can only occur before ARMv7
4635 MemU[address,4] = bits(32) UNKNOWN;
4636 if wback then R[n] = offset_addr;
4637#endif
4638
4639 bool success = false;
4640 const uint32_t opcode = OpcodeAsUnsigned (&success);
4641 if (!success)
4642 return false;
4643
4644 if (ConditionPassed())
4645 {
4646 const uint32_t addr_byte_size = GetAddressByteSize();
4647
4648 uint32_t t;
4649 uint32_t n;
4650 uint32_t m;
4651 ARM_ShifterType shift_t;
4652 uint32_t shift_n;
4653 bool index;
4654 bool add;
4655 bool wback;
4656
4657 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4658 switch (encoding)
4659 {
4660 case eEncodingT1:
4661 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4662 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4663 t = Bits32 (opcode, 2, 0);
4664 n = Bits32 (opcode, 5, 3);
4665 m = Bits32 (opcode, 8, 6);
4666
4667 // index = TRUE; add = TRUE; wback = FALSE;
4668 index = true;
4669 add = true;
4670 wback = false;
4671
4672 // (shift_t, shift_n) = (SRType_LSL, 0);
4673 shift_t = SRType_LSL;
4674 shift_n = 0;
4675 break;
4676
4677 case eEncodingT2:
4678 // if Rn == ’1111’ then UNDEFINED;
4679 if (Bits32 (opcode, 19, 16) == 15)
4680 return false;
4681
4682 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4683 t = Bits32 (opcode, 15, 12);
4684 n = Bits32 (opcode, 19, 16);
4685 m = Bits32 (opcode, 3, 0);
4686
4687 // index = TRUE; add = TRUE; wback = FALSE;
4688 index = true;
4689 add = true;
4690 wback = false;
4691
4692 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4693 shift_t = SRType_LSL;
4694 shift_n = Bits32 (opcode, 5, 4);
4695
4696 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4697 if ((t == 15) || (BadReg (m)))
4698 return false;
4699 break;
4700
4701 case eEncodingA1:
4702 {
4703 // if P == ’0’ && W == ’1’ then SEE STRT;
4704 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4705 t = Bits32 (opcode, 15, 12);
4706 n = Bits32 (opcode, 19, 16);
4707 m = Bits32 (opcode, 3, 0);
4708
4709 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4710 index = BitIsSet (opcode, 24);
4711 add = BitIsSet (opcode, 23);
4712 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4713
4714 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4715 uint32_t typ = Bits32 (opcode, 6, 5);
4716 uint32_t imm5 = Bits32 (opcode, 11, 7);
4717 shift_n = DecodeImmShift(typ, imm5, shift_t);
4718
4719 // if m == 15 then UNPREDICTABLE;
4720 if (m == 15)
4721 return false;
4722
4723 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4724 if (wback && ((n == 15) || (n == t)))
4725 return false;
4726
4727 break;
4728 }
4729 default:
4730 return false;
4731 }
4732
4733 addr_t offset_addr;
4734 addr_t address;
4735 int32_t offset = 0;
4736
4737 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4738 if (!success)
4739 return false;
4740
4741 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4742 if (!success)
4743 return false;
4744
4745 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004746 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004747
4748 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4749 if (add)
4750 offset_addr = base_address + offset;
4751 else
4752 offset_addr = base_address - offset;
4753
4754 // address = if index then offset_addr else R[n];
4755 if (index)
4756 address = offset_addr;
4757 else
4758 address = base_address;
4759
4760 uint32_t data;
4761 // if t == 15 then // Only possible for encoding A1
4762 if (t == 15)
4763 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004764 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004765 else
4766 // data = R[t];
4767 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4768
4769 if (!success)
4770 return false;
4771
4772 EmulateInstruction::Context context;
4773 context.type = eContextRegisterStore;
4774
4775 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4776 if (UnalignedSupport ()
4777 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4778 || CurrentInstrSet() == eModeARM)
4779 {
4780 // MemU[address,4] = data;
4781
4782 Register base_reg;
4783 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4784
4785 Register data_reg;
4786 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4787
4788 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004789 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004790 return false;
4791
4792 }
4793 else
4794 // MemU[address,4] = bits(32) UNKNOWN;
4795 WriteBits32UnknownToMemory (address);
4796
4797 // if wback then R[n] = offset_addr;
4798 if (wback)
4799 {
4800 context.type = eContextRegisterLoad;
4801 context.SetAddress (offset_addr);
4802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4803 return false;
4804 }
4805
4806 }
4807 return true;
4808}
Caroline Tice73a29de2011-02-16 20:22:22 +00004809
4810bool
4811EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4812{
4813#if 0
4814 if ConditionPassed() then
4815 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4816 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4817 address = if index then offset_addr else R[n];
4818 MemU[address,1] = R[t]<7:0>;
4819 if wback then R[n] = offset_addr;
4820#endif
4821
4822
4823 bool success = false;
4824 const uint32_t opcode = OpcodeAsUnsigned (&success);
4825 if (!success)
4826 return false;
4827
4828 if (ConditionPassed ())
4829 {
4830 uint32_t t;
4831 uint32_t n;
4832 uint32_t imm32;
4833 bool index;
4834 bool add;
4835 bool wback;
4836 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4837 switch (encoding)
4838 {
4839 case eEncodingT1:
4840 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4841 t = Bits32 (opcode, 2, 0);
4842 n = Bits32 (opcode, 5, 3);
4843 imm32 = Bits32 (opcode, 10, 6);
4844
4845 // index = TRUE; add = TRUE; wback = FALSE;
4846 index = true;
4847 add = true;
4848 wback = false;
4849 break;
4850
4851 case eEncodingT2:
4852 // if Rn == ’1111’ then UNDEFINED;
4853 if (Bits32 (opcode, 19, 16) == 15)
4854 return false;
4855
4856 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4857 t = Bits32 (opcode, 15, 12);
4858 n = Bits32 (opcode, 19, 16);
4859 imm32 = Bits32 (opcode, 11, 0);
4860
4861 // index = TRUE; add = TRUE; wback = FALSE;
4862 index = true;
4863 add = true;
4864 wback = false;
4865
4866 // if BadReg(t) then UNPREDICTABLE;
4867 if (BadReg (t))
4868 return false;
4869 break;
4870
4871 case eEncodingT3:
4872 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4873 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4874 if (Bits32 (opcode, 19, 16) == 15)
4875 return false;
4876
4877 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4878 t = Bits32 (opcode, 15, 12);
4879 n = Bits32 (opcode, 19, 16);
4880 imm32 = Bits32 (opcode, 7, 0);
4881
4882 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4883 index = BitIsSet (opcode, 10);
4884 add = BitIsSet (opcode, 9);
4885 wback = BitIsSet (opcode, 8);
4886
4887 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4888 if ((BadReg (t)) || (wback && (n == t)))
4889 return false;
4890 break;
4891
4892 default:
4893 return false;
4894 }
4895
4896 addr_t offset_addr;
4897 addr_t address;
4898 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4899 if (!success)
4900 return false;
4901
4902 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4903 if (add)
4904 offset_addr = base_address + imm32;
4905 else
4906 offset_addr = base_address - imm32;
4907
4908 // address = if index then offset_addr else R[n];
4909 if (index)
4910 address = offset_addr;
4911 else
4912 address = base_address;
4913
Caroline Ticecc96eb52011-02-17 19:20:40 +00004914 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004915 Register base_reg;
4916 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4917
4918 Register data_reg;
4919 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4920
4921 EmulateInstruction::Context context;
4922 context.type = eContextRegisterStore;
4923 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4924
4925 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4926 if (!success)
4927 return false;
4928
4929 data = Bits32 (data, 7, 0);
4930
Caroline Ticecc96eb52011-02-17 19:20:40 +00004931 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004932 return false;
4933
4934 // if wback then R[n] = offset_addr;
4935 if (wback)
4936 {
4937 context.type = eContextRegisterLoad;
4938 context.SetAddress (offset_addr);
4939 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4940 return false;
4941 }
4942
4943 }
4944
4945 return true;
4946}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004947
4948// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4949// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4950bool
4951EmulateInstructionARM::EmulateSTRHRegister (ARMEncoding encoding)
4952{
4953#if 0
4954 if ConditionPassed() then
4955 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4956 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4957 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4958 address = if index then offset_addr else R[n];
4959 if UnalignedSupport() || address<0> == ’0’ then
4960 MemU[address,2] = R[t]<15:0>;
4961 else // Can only occur before ARMv7
4962 MemU[address,2] = bits(16) UNKNOWN;
4963 if wback then R[n] = offset_addr;
4964#endif
4965
4966 bool success = false;
4967 const uint32_t opcode = OpcodeAsUnsigned (&success);
4968 if (!success)
4969 return false;
4970
4971 if (ConditionPassed ())
4972 {
4973 uint32_t t;
4974 uint32_t n;
4975 uint32_t m;
4976 bool index;
4977 bool add;
4978 bool wback;
4979 ARM_ShifterType shift_t;
4980 uint32_t shift_n;
4981
4982 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4983 switch (encoding)
4984 {
4985 case eEncodingT1:
4986 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4987 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4988 t = Bits32 (opcode, 2, 0);
4989 n = Bits32 (opcode, 5, 3);
4990 m = Bits32 (opcode, 8, 6);
4991
4992 // index = TRUE; add = TRUE; wback = FALSE;
4993 index = true;
4994 add = true;
4995 wback = false;
4996
4997 // (shift_t, shift_n) = (SRType_LSL, 0);
4998 shift_t = SRType_LSL;
4999 shift_n = 0;
5000
5001 break;
5002
5003 case eEncodingT2:
5004 // if Rn == ’1111’ then UNDEFINED;
5005 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5006 t = Bits32 (opcode, 15, 12);
5007 n = Bits32 (opcode, 19, 16);
5008 m = Bits32 (opcode, 3, 0);
5009 if (n == 15)
5010 return false;
5011
5012 // index = TRUE; add = TRUE; wback = FALSE;
5013 index = true;
5014 add = true;
5015 wback = false;
5016
5017 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5018 shift_t = SRType_LSL;
5019 shift_n = Bits32 (opcode, 5, 4);
5020
5021 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5022 if (BadReg (t) || BadReg (m))
5023 return false;
5024
5025 break;
5026
5027 case eEncodingA1:
5028 // if P == ’0’ && W == ’1’ then SEE STRHT;
5029 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5030 t = Bits32 (opcode, 15, 12);
5031 n = Bits32 (opcode, 19, 16);
5032 m = Bits32 (opcode, 3, 0);
5033
5034 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5035 index = BitIsSet (opcode, 24);
5036 add = BitIsSet (opcode, 23);
5037 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5038
5039 // (shift_t, shift_n) = (SRType_LSL, 0);
5040 shift_t = SRType_LSL;
5041 shift_n = 0;
5042
5043 // if t == 15 || m == 15 then UNPREDICTABLE;
5044 if ((t == 15) || (m == 15))
5045 return false;
5046
5047 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5048 if (wback && ((n == 15) || (n == t)))
5049 return false;
5050
5051 break;
5052
5053 default:
5054 return false;
5055 }
5056
5057 uint32_t Rm = ReadCoreReg (m, &success);
5058 if (!success)
5059 return false;
5060
5061 uint32_t Rn = ReadCoreReg (n, &success);
5062 if (!success)
5063 return false;
5064
5065 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5066 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5067
5068 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5069 addr_t offset_addr;
5070 if (add)
5071 offset_addr = Rn + offset;
5072 else
5073 offset_addr = Rn - offset;
5074
5075 // address = if index then offset_addr else R[n];
5076 addr_t address;
5077 if (index)
5078 address = offset_addr;
5079 else
5080 address = Rn;
5081
5082 EmulateInstruction::Context context;
5083 context.type = eContextRegisterStore;
5084 Register base_reg;
5085 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5086 Register offset_reg;
5087 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5088
5089 // if UnalignedSupport() || address<0> == ’0’ then
5090 if (UnalignedSupport() || BitIsClear (address, 0))
5091 {
5092 // MemU[address,2] = R[t]<15:0>;
5093 uint32_t Rt = ReadCoreReg (t, &success);
5094 if (!success)
5095 return false;
5096
5097 EmulateInstruction::Context context;
5098 context.type = eContextRegisterStore;
5099 Register base_reg;
5100 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5101 Register offset_reg;
5102 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5103 Register data_reg;
5104 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5105 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5106
5107 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5108 return false;
5109 }
5110 else // Can only occur before ARMv7
5111 {
5112 // MemU[address,2] = bits(16) UNKNOWN;
5113 }
5114
5115 // if wback then R[n] = offset_addr;
5116 if (wback)
5117 {
5118 context.type = eContextAdjustBaseRegister;
5119 context.SetAddress (offset_addr);
5120 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5121 return false;
5122 }
5123 }
5124
5125 return true;
5126}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005127
Johnny Chen157b9592011-02-18 21:13:05 +00005128// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5129// and writes the result to the destination register. It can optionally update the condition flags
5130// based on the result.
5131bool
5132EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
5133{
5134#if 0
5135 // ARM pseudo code...
5136 if ConditionPassed() then
5137 EncodingSpecificOperations();
5138 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5139 if d == 15 then // Can only occur for ARM encoding
5140 ALUWritePC(result); // setflags is always FALSE here
5141 else
5142 R[d] = result;
5143 if setflags then
5144 APSR.N = result<31>;
5145 APSR.Z = IsZeroBit(result);
5146 APSR.C = carry;
5147 APSR.V = overflow;
5148#endif
5149
5150 bool success = false;
5151 const uint32_t opcode = OpcodeAsUnsigned (&success);
5152 if (!success)
5153 return false;
5154
5155 if (ConditionPassed())
5156 {
5157 uint32_t Rd, Rn;
5158 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5159 bool setflags;
5160 switch (encoding)
5161 {
5162 case eEncodingT1:
5163 Rd = Bits32(opcode, 11, 8);
5164 Rn = Bits32(opcode, 19, 16);
5165 setflags = BitIsSet(opcode, 20);
5166 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5167 if (BadReg(Rd) || BadReg(Rn))
5168 return false;
5169 break;
5170 case eEncodingA1:
5171 Rd = Bits32(opcode, 15, 12);
5172 Rn = Bits32(opcode, 19, 16);
5173 setflags = BitIsSet(opcode, 20);
5174 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5175 // TODO: Emulate SUBS PC, LR and related instructions.
5176 if (Rd == 15 && setflags)
5177 return false;
5178 break;
5179 default:
5180 return false;
5181 }
5182
5183 // Read the first operand.
5184 int32_t val1 = ReadCoreReg(Rn, &success);
5185 if (!success)
5186 return false;
5187
5188 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5189
5190 EmulateInstruction::Context context;
5191 context.type = EmulateInstruction::eContextImmediate;
5192 context.SetNoArgs ();
5193
5194 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5195 return false;
5196 }
5197 return true;
5198}
5199
5200// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5201// register value, and writes the result to the destination register. It can optionally update the
5202// condition flags based on the result.
5203bool
5204EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
5205{
5206#if 0
5207 // ARM pseudo code...
5208 if ConditionPassed() then
5209 EncodingSpecificOperations();
5210 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5211 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5212 if d == 15 then // Can only occur for ARM encoding
5213 ALUWritePC(result); // setflags is always FALSE here
5214 else
5215 R[d] = result;
5216 if setflags then
5217 APSR.N = result<31>;
5218 APSR.Z = IsZeroBit(result);
5219 APSR.C = carry;
5220 APSR.V = overflow;
5221#endif
5222
5223 bool success = false;
5224 const uint32_t opcode = OpcodeAsUnsigned (&success);
5225 if (!success)
5226 return false;
5227
5228 if (ConditionPassed())
5229 {
5230 uint32_t Rd, Rn, Rm;
5231 ARM_ShifterType shift_t;
5232 uint32_t shift_n; // the shift applied to the value read from Rm
5233 bool setflags;
5234 switch (encoding)
5235 {
5236 case eEncodingT1:
5237 Rd = Rn = Bits32(opcode, 2, 0);
5238 Rm = Bits32(opcode, 5, 3);
5239 setflags = !InITBlock();
5240 shift_t = SRType_LSL;
5241 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005242 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005243 case eEncodingT2:
5244 Rd = Bits32(opcode, 11, 8);
5245 Rn = Bits32(opcode, 19, 16);
5246 Rm = Bits32(opcode, 3, 0);
5247 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005248 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005249 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5250 return false;
5251 break;
5252 case eEncodingA1:
5253 Rd = Bits32(opcode, 15, 12);
5254 Rn = Bits32(opcode, 19, 16);
5255 Rm = Bits32(opcode, 3, 0);
5256 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005257 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005258 // TODO: Emulate SUBS PC, LR and related instructions.
5259 if (Rd == 15 && setflags)
5260 return false;
5261 break;
5262 default:
5263 return false;
5264 }
5265
5266 // Read the first operand.
5267 int32_t val1 = ReadCoreReg(Rn, &success);
5268 if (!success)
5269 return false;
5270
5271 // Read the second operand.
5272 int32_t val2 = ReadCoreReg(Rm, &success);
5273 if (!success)
5274 return false;
5275
5276 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5277 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5278
5279 EmulateInstruction::Context context;
5280 context.type = EmulateInstruction::eContextImmediate;
5281 context.SetNoArgs ();
5282
5283 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5284 return false;
5285 }
5286 return true;
5287}
5288
Johnny Chena695f952011-02-23 21:24:25 +00005289// This instruction adds an immediate value to the PC value to form a PC-relative address,
5290// and writes the result to the destination register.
5291bool
5292EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
5293{
5294#if 0
5295 // ARM pseudo code...
5296 if ConditionPassed() then
5297 EncodingSpecificOperations();
5298 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5299 if d == 15 then // Can only occur for ARM encodings
5300 ALUWritePC(result);
5301 else
5302 R[d] = result;
5303#endif
5304
5305 bool success = false;
5306 const uint32_t opcode = OpcodeAsUnsigned (&success);
5307 if (!success)
5308 return false;
5309
5310 if (ConditionPassed())
5311 {
5312 uint32_t Rd;
5313 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5314 bool add;
5315 switch (encoding)
5316 {
5317 case eEncodingT1:
5318 Rd = Bits32(opcode, 10, 8);
5319 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5320 break;
5321 case eEncodingT2:
5322 case eEncodingT3:
5323 Rd = Bits32(opcode, 11, 8);
5324 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5325 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5326 if (BadReg(Rd))
5327 return false;
5328 break;
5329 case eEncodingA1:
5330 case eEncodingA2:
5331 Rd = Bits32(opcode, 15, 12);
5332 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5333 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5334 break;
5335 default:
5336 return false;
5337 }
5338
5339 // Read the PC value.
5340 uint32_t pc = ReadCoreReg(PC_REG, &success);
5341 if (!success)
5342 return false;
5343
5344 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5345
5346 EmulateInstruction::Context context;
5347 context.type = EmulateInstruction::eContextImmediate;
5348 context.SetNoArgs ();
5349
5350 if (!WriteCoreReg(context, result, Rd))
5351 return false;
5352 }
5353 return true;
5354}
5355
Johnny Chene97c0d52011-02-18 19:32:20 +00005356// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5357// to the destination register. It can optionally update the condition flags based on the result.
5358bool
5359EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5360{
5361#if 0
5362 // ARM pseudo code...
5363 if ConditionPassed() then
5364 EncodingSpecificOperations();
5365 result = R[n] AND imm32;
5366 if d == 15 then // Can only occur for ARM encoding
5367 ALUWritePC(result); // setflags is always FALSE here
5368 else
5369 R[d] = result;
5370 if setflags then
5371 APSR.N = result<31>;
5372 APSR.Z = IsZeroBit(result);
5373 APSR.C = carry;
5374 // APSR.V unchanged
5375#endif
5376
5377 bool success = false;
5378 const uint32_t opcode = OpcodeAsUnsigned (&success);
5379 if (!success)
5380 return false;
5381
5382 if (ConditionPassed())
5383 {
5384 uint32_t Rd, Rn;
5385 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5386 bool setflags;
5387 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5388 switch (encoding)
5389 {
5390 case eEncodingT1:
5391 Rd = Bits32(opcode, 11, 8);
5392 Rn = Bits32(opcode, 19, 16);
5393 setflags = BitIsSet(opcode, 20);
5394 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005395 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005396 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005397 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005398 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5399 return false;
5400 break;
5401 case eEncodingA1:
5402 Rd = Bits32(opcode, 15, 12);
5403 Rn = Bits32(opcode, 19, 16);
5404 setflags = BitIsSet(opcode, 20);
5405 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5406 // TODO: Emulate SUBS PC, LR and related instructions.
5407 if (Rd == 15 && setflags)
5408 return false;
5409 break;
5410 default:
5411 return false;
5412 }
5413
Johnny Chene97c0d52011-02-18 19:32:20 +00005414 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005415 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005416 if (!success)
5417 return false;
5418
5419 uint32_t result = val1 & imm32;
5420
5421 EmulateInstruction::Context context;
5422 context.type = EmulateInstruction::eContextImmediate;
5423 context.SetNoArgs ();
5424
5425 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5426 return false;
5427 }
5428 return true;
5429}
5430
5431// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5432// and writes the result to the destination register. It can optionally update the condition flags
5433// based on the result.
5434bool
5435EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5436{
5437#if 0
5438 // ARM pseudo code...
5439 if ConditionPassed() then
5440 EncodingSpecificOperations();
5441 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5442 result = R[n] AND shifted;
5443 if d == 15 then // Can only occur for ARM encoding
5444 ALUWritePC(result); // setflags is always FALSE here
5445 else
5446 R[d] = result;
5447 if setflags then
5448 APSR.N = result<31>;
5449 APSR.Z = IsZeroBit(result);
5450 APSR.C = carry;
5451 // APSR.V unchanged
5452#endif
5453
5454 bool success = false;
5455 const uint32_t opcode = OpcodeAsUnsigned (&success);
5456 if (!success)
5457 return false;
5458
5459 if (ConditionPassed())
5460 {
5461 uint32_t Rd, Rn, Rm;
5462 ARM_ShifterType shift_t;
5463 uint32_t shift_n; // the shift applied to the value read from Rm
5464 bool setflags;
5465 uint32_t carry;
5466 switch (encoding)
5467 {
5468 case eEncodingT1:
5469 Rd = Rn = Bits32(opcode, 2, 0);
5470 Rm = Bits32(opcode, 5, 3);
5471 setflags = !InITBlock();
5472 shift_t = SRType_LSL;
5473 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005474 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005475 case eEncodingT2:
5476 Rd = Bits32(opcode, 11, 8);
5477 Rn = Bits32(opcode, 19, 16);
5478 Rm = Bits32(opcode, 3, 0);
5479 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005480 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005481 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005482 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005483 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005484 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5485 return false;
5486 break;
5487 case eEncodingA1:
5488 Rd = Bits32(opcode, 15, 12);
5489 Rn = Bits32(opcode, 19, 16);
5490 Rm = Bits32(opcode, 3, 0);
5491 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005492 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005493 // TODO: Emulate SUBS PC, LR and related instructions.
5494 if (Rd == 15 && setflags)
5495 return false;
5496 break;
5497 default:
5498 return false;
5499 }
5500
Johnny Chene97c0d52011-02-18 19:32:20 +00005501 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005502 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005503 if (!success)
5504 return false;
5505
5506 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005507 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005508 if (!success)
5509 return false;
5510
5511 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5512 uint32_t result = val1 & shifted;
5513
5514 EmulateInstruction::Context context;
5515 context.type = EmulateInstruction::eContextImmediate;
5516 context.SetNoArgs ();
5517
5518 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5519 return false;
5520 }
5521 return true;
5522}
5523
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005524// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5525// immediate value, and writes the result to the destination register. It can optionally update the
5526// condition flags based on the result.
5527bool
5528EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5529{
5530#if 0
5531 // ARM pseudo code...
5532 if ConditionPassed() then
5533 EncodingSpecificOperations();
5534 result = R[n] AND NOT(imm32);
5535 if d == 15 then // Can only occur for ARM encoding
5536 ALUWritePC(result); // setflags is always FALSE here
5537 else
5538 R[d] = result;
5539 if setflags then
5540 APSR.N = result<31>;
5541 APSR.Z = IsZeroBit(result);
5542 APSR.C = carry;
5543 // APSR.V unchanged
5544#endif
5545
5546 bool success = false;
5547 const uint32_t opcode = OpcodeAsUnsigned (&success);
5548 if (!success)
5549 return false;
5550
5551 if (ConditionPassed())
5552 {
5553 uint32_t Rd, Rn;
5554 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5555 bool setflags;
5556 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5557 switch (encoding)
5558 {
5559 case eEncodingT1:
5560 Rd = Bits32(opcode, 11, 8);
5561 Rn = Bits32(opcode, 19, 16);
5562 setflags = BitIsSet(opcode, 20);
5563 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5564 if (BadReg(Rd) || BadReg(Rn))
5565 return false;
5566 break;
5567 case eEncodingA1:
5568 Rd = Bits32(opcode, 15, 12);
5569 Rn = Bits32(opcode, 19, 16);
5570 setflags = BitIsSet(opcode, 20);
5571 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5572 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5573 // TODO: Emulate SUBS PC, LR and related instructions.
5574 if (Rd == 15 && setflags)
5575 return false;
5576 break;
5577 default:
5578 return false;
5579 }
5580
5581 // Read the first operand.
5582 uint32_t val1 = ReadCoreReg(Rn, &success);
5583 if (!success)
5584 return false;
5585
5586 uint32_t result = val1 & ~imm32;
5587
5588 EmulateInstruction::Context context;
5589 context.type = EmulateInstruction::eContextImmediate;
5590 context.SetNoArgs ();
5591
5592 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5593 return false;
5594 }
5595 return true;
5596}
5597
5598// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5599// optionally-shifted register value, and writes the result to the destination register.
5600// It can optionally update the condition flags based on the result.
5601bool
5602EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5603{
5604#if 0
5605 // ARM pseudo code...
5606 if ConditionPassed() then
5607 EncodingSpecificOperations();
5608 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5609 result = R[n] AND NOT(shifted);
5610 if d == 15 then // Can only occur for ARM encoding
5611 ALUWritePC(result); // setflags is always FALSE here
5612 else
5613 R[d] = result;
5614 if setflags then
5615 APSR.N = result<31>;
5616 APSR.Z = IsZeroBit(result);
5617 APSR.C = carry;
5618 // APSR.V unchanged
5619#endif
5620
5621 bool success = false;
5622 const uint32_t opcode = OpcodeAsUnsigned (&success);
5623 if (!success)
5624 return false;
5625
5626 if (ConditionPassed())
5627 {
5628 uint32_t Rd, Rn, Rm;
5629 ARM_ShifterType shift_t;
5630 uint32_t shift_n; // the shift applied to the value read from Rm
5631 bool setflags;
5632 uint32_t carry;
5633 switch (encoding)
5634 {
5635 case eEncodingT1:
5636 Rd = Rn = Bits32(opcode, 2, 0);
5637 Rm = Bits32(opcode, 5, 3);
5638 setflags = !InITBlock();
5639 shift_t = SRType_LSL;
5640 shift_n = 0;
5641 break;
5642 case eEncodingT2:
5643 Rd = Bits32(opcode, 11, 8);
5644 Rn = Bits32(opcode, 19, 16);
5645 Rm = Bits32(opcode, 3, 0);
5646 setflags = BitIsSet(opcode, 20);
5647 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5648 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5649 return false;
5650 break;
5651 case eEncodingA1:
5652 Rd = Bits32(opcode, 15, 12);
5653 Rn = Bits32(opcode, 19, 16);
5654 Rm = Bits32(opcode, 3, 0);
5655 setflags = BitIsSet(opcode, 20);
5656 shift_n = DecodeImmShiftARM(opcode, shift_t);
5657 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5658 // TODO: Emulate SUBS PC, LR and related instructions.
5659 if (Rd == 15 && setflags)
5660 return false;
5661 break;
5662 default:
5663 return false;
5664 }
5665
5666 // Read the first operand.
5667 uint32_t val1 = ReadCoreReg(Rn, &success);
5668 if (!success)
5669 return false;
5670
5671 // Read the second operand.
5672 uint32_t val2 = ReadCoreReg(Rm, &success);
5673 if (!success)
5674 return false;
5675
5676 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5677 uint32_t result = val1 & ~shifted;
5678
5679 EmulateInstruction::Context context;
5680 context.type = EmulateInstruction::eContextImmediate;
5681 context.SetNoArgs ();
5682
5683 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5684 return false;
5685 }
5686 return true;
5687}
5688
Caroline Tice4d729c52011-02-18 00:55:53 +00005689// 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 +00005690// 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 +00005691bool
5692EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5693{
5694#if 0
5695 if ConditionPassed() then
5696 EncodingSpecificOperations();
5697 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5698 address = if index then offset_addr else R[n];
5699 data = MemU[address,4];
5700 if wback then R[n] = offset_addr;
5701 if t == 15 then
5702 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5703 elsif UnalignedSupport() || address<1:0> = ’00’ then
5704 R[t] = data;
5705 else // Can only apply before ARMv7
5706 R[t] = ROR(data, 8*UInt(address<1:0>));
5707#endif
5708
5709 bool success = false;
5710 const uint32_t opcode = OpcodeAsUnsigned (&success);
5711 if (!success)
5712 return false;
5713
5714 if (ConditionPassed ())
5715 {
5716 const uint32_t addr_byte_size = GetAddressByteSize();
5717
5718 uint32_t t;
5719 uint32_t n;
5720 uint32_t imm32;
5721 bool index;
5722 bool add;
5723 bool wback;
5724
5725 switch (encoding)
5726 {
5727 case eEncodingA1:
5728 // if Rn == ’1111’ then SEE LDR (literal);
5729 // if P == ’0’ && W == ’1’ then SEE LDRT;
5730 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5731 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5732 t = Bits32 (opcode, 15, 12);
5733 n = Bits32 (opcode, 19, 16);
5734 imm32 = Bits32 (opcode, 11, 0);
5735
5736 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5737 index = BitIsSet (opcode, 24);
5738 add = BitIsSet (opcode, 23);
5739 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5740
5741 // if wback && n == t then UNPREDICTABLE;
5742 if (wback && (n == t))
5743 return false;
5744
5745 break;
5746
5747 default:
5748 return false;
5749 }
5750
5751 addr_t address;
5752 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005753 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005754 if (!success)
5755 return false;
5756
5757 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5758 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005759 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005760 else
5761 offset_addr = base_address - imm32;
5762
5763 // address = if index then offset_addr else R[n];
5764 if (index)
5765 address = offset_addr;
5766 else
5767 address = base_address;
5768
5769 // data = MemU[address,4];
5770
5771 Register base_reg;
5772 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5773
5774 EmulateInstruction::Context context;
5775 context.type = eContextRegisterLoad;
5776 context.SetRegisterPlusOffset (base_reg, address - base_address);
5777
5778 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5779 if (!success)
5780 return false;
5781
5782 // if wback then R[n] = offset_addr;
5783 if (wback)
5784 {
5785 context.type = eContextAdjustBaseRegister;
5786 context.SetAddress (offset_addr);
5787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5788 return false;
5789 }
5790
5791 // if t == 15 then
5792 if (t == 15)
5793 {
5794 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5795 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5796 {
5797 // LoadWritePC (data);
5798 context.type = eContextRegisterLoad;
5799 context.SetRegisterPlusOffset (base_reg, address - base_address);
5800 LoadWritePC (context, data);
5801 }
5802 else
5803 return false;
5804 }
5805 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5806 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5807 {
5808 // R[t] = data;
5809 context.type = eContextRegisterLoad;
5810 context.SetRegisterPlusOffset (base_reg, address - base_address);
5811 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5812 return false;
5813 }
5814 // else // Can only apply before ARMv7
5815 else
5816 {
5817 // R[t] = ROR(data, 8*UInt(address<1:0>));
5818 data = ROR (data, Bits32 (address, 1, 0));
5819 context.type = eContextRegisterLoad;
5820 context.SetImmediate (data);
5821 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5822 return false;
5823 }
5824
5825 }
5826 return true;
5827}
5828
Caroline Ticefe479112011-02-18 18:52:37 +00005829// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5830// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5831bool
5832EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5833{
5834#if 0
5835 if ConditionPassed() then
5836 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5837 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5838 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5839 address = if index then offset_addr else R[n];
5840 data = MemU[address,4];
5841 if wback then R[n] = offset_addr;
5842 if t == 15 then
5843 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5844 elsif UnalignedSupport() || address<1:0> = ’00’ then
5845 R[t] = data;
5846 else // Can only apply before ARMv7
5847 if CurrentInstrSet() == InstrSet_ARM then
5848 R[t] = ROR(data, 8*UInt(address<1:0>));
5849 else
5850 R[t] = bits(32) UNKNOWN;
5851#endif
5852
5853 bool success = false;
5854 const uint32_t opcode = OpcodeAsUnsigned (&success);
5855 if (!success)
5856 return false;
5857
5858 if (ConditionPassed ())
5859 {
5860 const uint32_t addr_byte_size = GetAddressByteSize();
5861
5862 uint32_t t;
5863 uint32_t n;
5864 uint32_t m;
5865 bool index;
5866 bool add;
5867 bool wback;
5868 ARM_ShifterType shift_t;
5869 uint32_t shift_n;
5870
5871 switch (encoding)
5872 {
5873 case eEncodingT1:
5874 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5875 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5876 t = Bits32 (opcode, 2, 0);
5877 n = Bits32 (opcode, 5, 3);
5878 m = Bits32 (opcode, 8, 6);
5879
5880 // index = TRUE; add = TRUE; wback = FALSE;
5881 index = true;
5882 add = true;
5883 wback = false;
5884
5885 // (shift_t, shift_n) = (SRType_LSL, 0);
5886 shift_t = SRType_LSL;
5887 shift_n = 0;
5888
5889 break;
5890
5891 case eEncodingT2:
5892 // if Rn == ’1111’ then SEE LDR (literal);
5893 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5894 t = Bits32 (opcode, 15, 12);
5895 n = Bits32 (opcode, 19, 16);
5896 m = Bits32 (opcode, 3, 0);
5897
5898 // index = TRUE; add = TRUE; wback = FALSE;
5899 index = true;
5900 add = true;
5901 wback = false;
5902
5903 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5904 shift_t = SRType_LSL;
5905 shift_n = Bits32 (opcode, 5, 4);
5906
5907 // if BadReg(m) then UNPREDICTABLE;
5908 if (BadReg (m))
5909 return false;
5910
5911 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5912 if ((t == 15) && InITBlock() && !LastInITBlock())
5913 return false;
5914
5915 break;
5916
5917 case eEncodingA1:
5918 {
5919 // if P == ’0’ && W == ’1’ then SEE LDRT;
5920 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5921 t = Bits32 (opcode, 15, 12);
5922 n = Bits32 (opcode, 19, 16);
5923 m = Bits32 (opcode, 3, 0);
5924
5925 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5926 index = BitIsSet (opcode, 24);
5927 add = BitIsSet (opcode, 23);
5928 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5929
5930 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5931 uint32_t type = Bits32 (opcode, 6, 5);
5932 uint32_t imm5 = Bits32 (opcode, 11, 7);
5933 shift_n = DecodeImmShift (type, imm5, shift_t);
5934
5935 // if m == 15 then UNPREDICTABLE;
5936 if (m == 15)
5937 return false;
5938
5939 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5940 if (wback && ((n == 15) || (n == t)))
5941 return false;
5942 }
5943 break;
5944
5945
5946 default:
5947 return false;
5948 }
5949
5950 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5951 if (!success)
5952 return false;
5953
5954 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5955 if (!success)
5956 return false;
5957
5958 addr_t offset_addr;
5959 addr_t address;
5960
5961 // 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 +00005962 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005963
5964 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5965 if (add)
5966 offset_addr = Rn + offset;
5967 else
5968 offset_addr = Rn - offset;
5969
5970 // address = if index then offset_addr else R[n];
5971 if (index)
5972 address = offset_addr;
5973 else
5974 address = Rn;
5975
5976 // data = MemU[address,4];
5977 Register base_reg;
5978 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5979
5980 EmulateInstruction::Context context;
5981 context.type = eContextRegisterLoad;
5982 context.SetRegisterPlusOffset (base_reg, address - Rn);
5983
5984 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5985 if (!success)
5986 return false;
5987
5988 // if wback then R[n] = offset_addr;
5989 if (wback)
5990 {
5991 context.type = eContextAdjustBaseRegister;
5992 context.SetAddress (offset_addr);
5993 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5994 return false;
5995 }
5996
5997 // if t == 15 then
5998 if (t == 15)
5999 {
6000 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
6001 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6002 {
6003 context.type = eContextRegisterLoad;
6004 context.SetRegisterPlusOffset (base_reg, address - Rn);
6005 LoadWritePC (context, data);
6006 }
6007 else
6008 return false;
6009 }
6010 // elsif UnalignedSupport() || address<1:0> = ’00’ then
6011 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6012 {
6013 // R[t] = data;
6014 context.type = eContextRegisterLoad;
6015 context.SetRegisterPlusOffset (base_reg, address - Rn);
6016 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6017 return false;
6018 }
6019 else // Can only apply before ARMv7
6020 {
6021 // if CurrentInstrSet() == InstrSet_ARM then
6022 if (CurrentInstrSet () == eModeARM)
6023 {
6024 // R[t] = ROR(data, 8*UInt(address<1:0>));
6025 data = ROR (data, Bits32 (address, 1, 0));
6026 context.type = eContextRegisterLoad;
6027 context.SetImmediate (data);
6028 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6029 return false;
6030 }
6031 else
6032 {
6033 // R[t] = bits(32) UNKNOWN;
6034 WriteBits32Unknown (t);
6035 }
6036 }
6037 }
6038 return true;
6039}
Caroline Tice21b604b2011-02-18 21:06:04 +00006040
6041// LDRB (immediate, Thumb)
6042bool
6043EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
6044{
6045#if 0
6046 if ConditionPassed() then
6047 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6048 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6049 address = if index then offset_addr else R[n];
6050 R[t] = ZeroExtend(MemU[address,1], 32);
6051 if wback then R[n] = offset_addr;
6052#endif
6053
6054 bool success = false;
6055 const uint32_t opcode = OpcodeAsUnsigned (&success);
6056 if (!success)
6057 return false;
6058
6059 if (ConditionPassed ())
6060 {
6061 uint32_t t;
6062 uint32_t n;
6063 uint32_t imm32;
6064 bool index;
6065 bool add;
6066 bool wback;
6067
6068 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6069 switch (encoding)
6070 {
6071 case eEncodingT1:
6072 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6073 t = Bits32 (opcode, 2, 0);
6074 n = Bits32 (opcode, 5, 3);
6075 imm32 = Bits32 (opcode, 10, 6);
6076
6077 // index = TRUE; add = TRUE; wback = FALSE;
6078 index = true;
6079 add = true;
6080 wback= false;
6081
6082 break;
6083
6084 case eEncodingT2:
6085 // if Rt == ’1111’ then SEE PLD;
6086 // if Rn == ’1111’ then SEE LDRB (literal);
6087 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6088 t = Bits32 (opcode, 15, 12);
6089 n = Bits32 (opcode, 19, 16);
6090 imm32 = Bits32 (opcode, 11, 0);
6091
6092 // index = TRUE; add = TRUE; wback = FALSE;
6093 index = true;
6094 add = true;
6095 wback = false;
6096
6097 // if t == 13 then UNPREDICTABLE;
6098 if (t == 13)
6099 return false;
6100
6101 break;
6102
6103 case eEncodingT3:
6104 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
6105 // if Rn == ’1111’ then SEE LDRB (literal);
6106 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
6107 // if P == ’0’ && W == ’0’ then UNDEFINED;
6108 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6109 return false;
6110
6111 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6112 t = Bits32 (opcode, 15, 12);
6113 n = Bits32 (opcode, 19, 16);
6114 imm32 = Bits32 (opcode, 7, 0);
6115
6116 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6117 index = BitIsSet (opcode, 10);
6118 add = BitIsSet (opcode, 9);
6119 wback = BitIsSet (opcode, 8);
6120
6121 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6122 if (BadReg (t) || (wback && (n == t)))
6123 return false;
6124
6125 break;
6126
6127 default:
6128 return false;
6129 }
6130
6131 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6132 if (!success)
6133 return false;
6134
6135 addr_t address;
6136 addr_t offset_addr;
6137
6138 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6139 if (add)
6140 offset_addr = Rn + imm32;
6141 else
6142 offset_addr = Rn - imm32;
6143
6144 // address = if index then offset_addr else R[n];
6145 if (index)
6146 address = offset_addr;
6147 else
6148 address = Rn;
6149
6150 // R[t] = ZeroExtend(MemU[address,1], 32);
6151 Register base_reg;
6152 Register data_reg;
6153 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6154 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6155
6156 EmulateInstruction::Context context;
6157 context.type = eContextRegisterLoad;
6158 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6159
6160 uint64_t data = MemURead (context, address, 1, 0, &success);
6161 if (!success)
6162 return false;
6163
6164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6165 return false;
6166
6167 // if wback then R[n] = offset_addr;
6168 if (wback)
6169 {
6170 context.type = eContextAdjustBaseRegister;
6171 context.SetAddress (offset_addr);
6172 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6173 return false;
6174 }
6175 }
6176 return true;
6177}
Caroline Ticef55261f2011-02-18 22:24:22 +00006178
6179// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6180// zero-extends it to form a 32-bit word and writes it to a register.
6181bool
6182EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
6183{
6184#if 0
6185 if ConditionPassed() then
6186 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6187 base = Align(PC,4);
6188 address = if add then (base + imm32) else (base - imm32);
6189 R[t] = ZeroExtend(MemU[address,1], 32);
6190#endif
6191
6192 bool success = false;
6193 const uint32_t opcode = OpcodeAsUnsigned (&success);
6194 if (!success)
6195 return false;
6196
6197 if (ConditionPassed ())
6198 {
6199 uint32_t t;
6200 uint32_t imm32;
6201 bool add;
6202 switch (encoding)
6203 {
6204 case eEncodingT1:
6205 // if Rt == ’1111’ then SEE PLD;
6206 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6207 t = Bits32 (opcode, 15, 12);
6208 imm32 = Bits32 (opcode, 11, 0);
6209 add = BitIsSet (opcode, 23);
6210
6211 // if t == 13 then UNPREDICTABLE;
6212 if (t == 13)
6213 return false;
6214
6215 break;
6216
6217 case eEncodingA1:
6218 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6219 t = Bits32 (opcode, 15, 12);
6220 imm32 = Bits32 (opcode, 11, 0);
6221 add = BitIsSet (opcode, 23);
6222
6223 // if t == 15 then UNPREDICTABLE;
6224 if (t == 15)
6225 return false;
6226 break;
6227
6228 default:
6229 return false;
6230 }
6231
6232 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006233 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006234 if (!success)
6235 return false;
6236
6237 uint32_t base = AlignPC (pc_val);
6238
6239 addr_t address;
6240 // address = if add then (base + imm32) else (base - imm32);
6241 if (add)
6242 address = base + imm32;
6243 else
6244 address = base - imm32;
6245
6246 // R[t] = ZeroExtend(MemU[address,1], 32);
6247 EmulateInstruction::Context context;
6248 context.type = eContextRelativeBranchImmediate;
6249 context.SetImmediate (address - base);
6250
6251 uint64_t data = MemURead (context, address, 1, 0, &success);
6252 if (!success)
6253 return false;
6254
6255 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6256 return false;
6257 }
6258 return true;
6259}
Caroline Tice30fec122011-02-18 23:52:21 +00006260
6261// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6262// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6263// optionally be shifted.
6264bool
6265EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
6266{
6267#if 0
6268 if ConditionPassed() then
6269 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6270 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6271 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6272 address = if index then offset_addr else R[n];
6273 R[t] = ZeroExtend(MemU[address,1],32);
6274 if wback then R[n] = offset_addr;
6275#endif
6276
6277 bool success = false;
6278 const uint32_t opcode = OpcodeAsUnsigned (&success);
6279 if (!success)
6280 return false;
6281
6282 if (ConditionPassed ())
6283 {
6284 uint32_t t;
6285 uint32_t n;
6286 uint32_t m;
6287 bool index;
6288 bool add;
6289 bool wback;
6290 ARM_ShifterType shift_t;
6291 uint32_t shift_n;
6292
6293 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6294 switch (encoding)
6295 {
6296 case eEncodingT1:
6297 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6298 t = Bits32 (opcode, 2, 0);
6299 n = Bits32 (opcode, 5, 3);
6300 m = Bits32 (opcode, 8, 6);
6301
6302 // index = TRUE; add = TRUE; wback = FALSE;
6303 index = true;
6304 add = true;
6305 wback = false;
6306
6307 // (shift_t, shift_n) = (SRType_LSL, 0);
6308 shift_t = SRType_LSL;
6309 shift_n = 0;
6310 break;
6311
6312 case eEncodingT2:
6313 // if Rt == ’1111’ then SEE PLD;
6314 // if Rn == ’1111’ then SEE LDRB (literal);
6315 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6316 t = Bits32 (opcode, 15, 12);
6317 n = Bits32 (opcode, 19, 16);
6318 m = Bits32 (opcode, 3, 0);
6319
6320 // index = TRUE; add = TRUE; wback = FALSE;
6321 index = true;
6322 add = true;
6323 wback = false;
6324
6325 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6326 shift_t = SRType_LSL;
6327 shift_n = Bits32 (opcode, 5, 4);
6328
6329 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6330 if ((t == 13) || BadReg (m))
6331 return false;
6332 break;
6333
6334 case eEncodingA1:
6335 {
6336 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6337 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6338 t = Bits32 (opcode, 15, 12);
6339 n = Bits32 (opcode, 19, 16);
6340 m = Bits32 (opcode, 3, 0);
6341
6342 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6343 index = BitIsSet (opcode, 24);
6344 add = BitIsSet (opcode, 23);
6345 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6346
6347 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6348 uint32_t type = Bits32 (opcode, 6, 5);
6349 uint32_t imm5 = Bits32 (opcode, 11, 7);
6350 shift_n = DecodeImmShift (type, imm5, shift_t);
6351
6352 // if t == 15 || m == 15 then UNPREDICTABLE;
6353 if ((t == 15) || (m == 15))
6354 return false;
6355
6356 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6357 if (wback && ((n == 15) || (n == t)))
6358 return false;
6359 }
6360 break;
6361
6362 default:
6363 return false;
6364 }
6365
6366 addr_t offset_addr;
6367 addr_t address;
6368
6369 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6370 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6371 if (!success)
6372 return false;
6373
6374 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6375
6376 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6377 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6378 if (!success)
6379 return false;
6380
6381 if (add)
6382 offset_addr = Rn + offset;
6383 else
6384 offset_addr = Rn - offset;
6385
6386 // address = if index then offset_addr else R[n];
6387 if (index)
6388 address = offset_addr;
6389 else
6390 address = Rn;
6391
6392 // R[t] = ZeroExtend(MemU[address,1],32);
6393 Register base_reg;
6394 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6395
6396 EmulateInstruction::Context context;
6397 context.type = eContextRegisterLoad;
6398 context.SetRegisterPlusOffset (base_reg, address - Rn);
6399
6400 uint64_t data = MemURead (context, address, 1, 0, &success);
6401 if (!success)
6402 return false;
6403
6404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6405 return false;
6406
6407 // if wback then R[n] = offset_addr;
6408 if (wback)
6409 {
6410 context.type = eContextAdjustBaseRegister;
6411 context.SetAddress (offset_addr);
6412 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6413 return false;
6414 }
6415 }
6416 return true;
6417}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006418
6419// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6420// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6421// post-indexed, or pre-indexed addressing.
6422bool
6423EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6424{
6425#if 0
6426 if ConditionPassed() then
6427 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6428 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6429 address = if index then offset_addr else R[n];
6430 data = MemU[address,2];
6431 if wback then R[n] = offset_addr;
6432 if UnalignedSupport() || address<0> = ’0’ then
6433 R[t] = ZeroExtend(data, 32);
6434 else // Can only apply before ARMv7
6435 R[t] = bits(32) UNKNOWN;
6436#endif
6437
6438
6439 bool success = false;
6440 const uint32_t opcode = OpcodeAsUnsigned (&success);
6441 if (!success)
6442 return false;
6443
6444 if (ConditionPassed())
6445 {
6446 uint32_t t;
6447 uint32_t n;
6448 uint32_t imm32;
6449 bool index;
6450 bool add;
6451 bool wback;
6452
6453 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6454 switch (encoding)
6455 {
6456 case eEncodingT1:
6457 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6458 t = Bits32 (opcode, 2, 0);
6459 n = Bits32 (opcode, 5, 3);
6460 imm32 = Bits32 (opcode, 10, 6) << 1;
6461
6462 // index = TRUE; add = TRUE; wback = FALSE;
6463 index = true;
6464 add = true;
6465 wback = false;
6466
6467 break;
6468
6469 case eEncodingT2:
6470 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6471 // if Rn == ’1111’ then SEE LDRH (literal);
6472 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6473 t = Bits32 (opcode, 15, 12);
6474 n = Bits32 (opcode, 19, 16);
6475 imm32 = Bits32 (opcode, 11, 0);
6476
6477 // index = TRUE; add = TRUE; wback = FALSE;
6478 index = true;
6479 add = true;
6480 wback = false;
6481
6482 // if t == 13 then UNPREDICTABLE;
6483 if (t == 13)
6484 return false;
6485 break;
6486
6487 case eEncodingT3:
6488 // if Rn == ’1111’ then SEE LDRH (literal);
6489 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6490 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6491 // if P == ’0’ && W == ’0’ then UNDEFINED;
6492 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6493 return false;
6494
6495 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6496 t = Bits32 (opcode, 15, 12);
6497 n = Bits32 (opcode, 19, 16);
6498 imm32 = Bits32 (opcode, 7, 0);
6499
6500 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6501 index = BitIsSet (opcode, 10);
6502 add = BitIsSet (opcode, 9);
6503 wback = BitIsSet (opcode, 8);
6504
6505 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6506 if (BadReg (t) || (wback && (n == t)))
6507 return false;
6508 break;
6509
6510 default:
6511 return false;
6512 }
6513
6514 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6515 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6516 if (!success)
6517 return false;
6518
6519 addr_t offset_addr;
6520 addr_t address;
6521
6522 if (add)
6523 offset_addr = Rn + imm32;
6524 else
6525 offset_addr = Rn - imm32;
6526
6527 // address = if index then offset_addr else R[n];
6528 if (index)
6529 address = offset_addr;
6530 else
6531 address = Rn;
6532
6533 // data = MemU[address,2];
6534 Register base_reg;
6535 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6536
6537 EmulateInstruction::Context context;
6538 context.type = eContextRegisterLoad;
6539 context.SetRegisterPlusOffset (base_reg, address - Rn);
6540
6541 uint64_t data = MemURead (context, address, 2, 0, &success);
6542 if (!success)
6543 return false;
6544
6545 // if wback then R[n] = offset_addr;
6546 if (wback)
6547 {
6548 context.type = eContextAdjustBaseRegister;
6549 context.SetAddress (offset_addr);
6550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6551 return false;
6552 }
6553
6554 // if UnalignedSupport() || address<0> = ’0’ then
6555 if (UnalignedSupport () || BitIsClear (address, 0))
6556 {
6557 // R[t] = ZeroExtend(data, 32);
6558 context.type = eContextRegisterLoad;
6559 context.SetRegisterPlusOffset (base_reg, address - Rn);
6560 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6561 return false;
6562 }
6563 else // Can only apply before ARMv7
6564 {
6565 // R[t] = bits(32) UNKNOWN;
6566 WriteBits32Unknown (t);
6567 }
6568 }
6569 return true;
6570}
Caroline Ticefe479112011-02-18 18:52:37 +00006571
Caroline Tice952b5382011-02-28 23:15:24 +00006572// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6573// zero-extends it to form a 32-bit word, and writes it to a register.
6574bool
6575EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6576{
6577#if 0
6578 if ConditionPassed() then
6579 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6580 base = Align(PC,4);
6581 address = if add then (base + imm32) else (base - imm32);
6582 data = MemU[address,2];
6583 if UnalignedSupport() || address<0> = ’0’ then
6584 R[t] = ZeroExtend(data, 32);
6585 else // Can only apply before ARMv7
6586 R[t] = bits(32) UNKNOWN;
6587#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006588
Caroline Tice952b5382011-02-28 23:15:24 +00006589 bool success = false;
6590 const uint32_t opcode = OpcodeAsUnsigned (&success);
6591 if (!success)
6592 return false;
6593
6594 if (ConditionPassed())
6595 {
6596 uint32_t t;
6597 uint32_t imm32;
6598 bool add;
6599
6600 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6601 switch (encoding)
6602 {
6603 case eEncodingT1:
6604 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6605 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6606 t = Bits32 (opcode, 15, 12);
6607 imm32 = Bits32 (opcode, 11, 0);
6608 add = BitIsSet (opcode, 23);
6609
6610 // if t == 13 then UNPREDICTABLE;
6611 if (t == 13)
6612 return false;
6613
6614 break;
6615
6616 case eEncodingA1:
6617 {
6618 uint32_t imm4H = Bits32 (opcode, 11, 8);
6619 uint32_t imm4L = Bits32 (opcode, 3, 0);
6620
6621 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6622 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006623 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006624 add = BitIsSet (opcode, 23);
6625
6626 // if t == 15 then UNPREDICTABLE;
6627 if (t == 15)
6628 return false;
6629 break;
6630 }
6631
6632 default:
6633 return false;
6634 }
6635
6636 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006637 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006638 if (!success)
6639 return false;
6640
6641 addr_t base = AlignPC (pc_value);
6642 addr_t address;
6643
6644 // address = if add then (base + imm32) else (base - imm32);
6645 if (add)
6646 address = base + imm32;
6647 else
6648 address = base - imm32;
6649
6650 // data = MemU[address,2];
6651 Register base_reg;
6652 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6653
6654 EmulateInstruction::Context context;
6655 context.type = eContextRegisterLoad;
6656 context.SetRegisterPlusOffset (base_reg, address - base);
6657
6658 uint64_t data = MemURead (context, address, 2, 0, &success);
6659 if (!success)
6660 return false;
6661
6662
6663 // if UnalignedSupport() || address<0> = ’0’ then
6664 if (UnalignedSupport () || BitIsClear (address, 0))
6665 {
6666 // R[t] = ZeroExtend(data, 32);
6667 context.type = eContextRegisterLoad;
6668 context.SetRegisterPlusOffset (base_reg, address - base);
6669 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6670 return false;
6671
6672 }
6673 else // Can only apply before ARMv7
6674 {
6675 // R[t] = bits(32) UNKNOWN;
6676 WriteBits32Unknown (t);
6677 }
6678 }
6679 return true;
6680}
6681
Caroline Tice0e6bc952011-03-01 18:00:42 +00006682// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6683// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6684// be shifted left by 0, 1, 2, or 3 bits.
6685bool
6686EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6687{
6688#if 0
6689 if ConditionPassed() then
6690 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6691 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6692 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6693 address = if index then offset_addr else R[n];
6694 data = MemU[address,2];
6695 if wback then R[n] = offset_addr;
6696 if UnalignedSupport() || address<0> = ’0’ then
6697 R[t] = ZeroExtend(data, 32);
6698 else // Can only apply before ARMv7
6699 R[t] = bits(32) UNKNOWN;
6700#endif
6701
6702 bool success = false;
6703 const uint32_t opcode = OpcodeAsUnsigned (&success);
6704 if (!success)
6705 return false;
6706
6707 if (ConditionPassed())
6708 {
6709 uint32_t t;
6710 uint32_t n;
6711 uint32_t m;
6712 bool index;
6713 bool add;
6714 bool wback;
6715 ARM_ShifterType shift_t;
6716 uint32_t shift_n;
6717
6718 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6719 switch (encoding)
6720 {
6721 case eEncodingT1:
6722 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6723 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6724 t = Bits32 (opcode, 2, 0);
6725 n = Bits32 (opcode, 5, 3);
6726 m = Bits32 (opcode, 8, 6);
6727
6728 // index = TRUE; add = TRUE; wback = FALSE;
6729 index = true;
6730 add = true;
6731 wback = false;
6732
6733 // (shift_t, shift_n) = (SRType_LSL, 0);
6734 shift_t = SRType_LSL;
6735 shift_n = 0;
6736
6737 break;
6738
6739 case eEncodingT2:
6740 // if Rn == ’1111’ then SEE LDRH (literal);
6741 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6742 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6743 t = Bits32 (opcode, 15, 12);
6744 n = Bits32 (opcode, 19, 16);
6745 m = Bits32 (opcode, 3, 0);
6746
6747 // index = TRUE; add = TRUE; wback = FALSE;
6748 index = true;
6749 add = true;
6750 wback = false;
6751
6752 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6753 shift_t = SRType_LSL;
6754 shift_n = Bits32 (opcode, 5, 4);
6755
6756 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6757 if ((t == 13) || BadReg (m))
6758 return false;
6759 break;
6760
6761 case eEncodingA1:
6762 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6763 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6764 t = Bits32 (opcode, 15, 12);
6765 n = Bits32 (opcode, 19, 16);
6766 m = Bits32 (opcode, 3, 0);
6767
6768 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6769 index = BitIsSet (opcode, 24);
6770 add = BitIsSet (opcode, 23);
6771 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6772
6773 // (shift_t, shift_n) = (SRType_LSL, 0);
6774 shift_t = SRType_LSL;
6775 shift_n = 0;
6776
6777 // if t == 15 || m == 15 then UNPREDICTABLE;
6778 if ((t == 15) || (m == 15))
6779 return false;
6780
6781 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6782 if (wback && ((n == 15) || (n == t)))
6783 return false;
6784
6785 break;
6786
6787 default:
6788 return false;
6789 }
6790
6791 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6792
6793 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6794 if (!success)
6795 return false;
6796
6797 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6798
6799 addr_t offset_addr;
6800 addr_t address;
6801
6802 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6803 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6804 if (!success)
6805 return false;
6806
6807 if (add)
6808 offset_addr = Rn + offset;
6809 else
6810 offset_addr = Rn - offset;
6811
6812 // address = if index then offset_addr else R[n];
6813 if (index)
6814 address = offset_addr;
6815 else
6816 address = Rn;
6817
6818 // data = MemU[address,2];
6819 Register base_reg;
6820 Register offset_reg;
6821 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6822 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6823
6824 EmulateInstruction::Context context;
6825 context.type = eContextRegisterLoad;
6826 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6827 uint64_t data = MemURead (context, address, 2, 0, &success);
6828 if (!success)
6829 return false;
6830
6831 // if wback then R[n] = offset_addr;
6832 if (wback)
6833 {
6834 context.type = eContextAdjustBaseRegister;
6835 context.SetAddress (offset_addr);
6836 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6837 return false;
6838 }
6839
6840 // if UnalignedSupport() || address<0> = ’0’ then
6841 if (UnalignedSupport() || BitIsClear (address, 0))
6842 {
6843 // R[t] = ZeroExtend(data, 32);
6844 context.type = eContextRegisterLoad;
6845 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6846 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6847 return false;
6848 }
6849 else // Can only apply before ARMv7
6850 {
6851 // R[t] = bits(32) UNKNOWN;
6852 WriteBits32Unknown (t);
6853 }
6854 }
6855 return true;
6856}
6857
Caroline Ticea5e28af2011-03-01 21:53:03 +00006858// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6859// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6860// or pre-indexed addressing.
6861bool
6862EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6863{
6864#if 0
6865 if ConditionPassed() then
6866 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6867 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6868 address = if index then offset_addr else R[n];
6869 R[t] = SignExtend(MemU[address,1], 32);
6870 if wback then R[n] = offset_addr;
6871#endif
6872
6873 bool success = false;
6874 const uint32_t opcode = OpcodeAsUnsigned (&success);
6875 if (!success)
6876 return false;
6877
6878 if (ConditionPassed ())
6879 {
6880 uint32_t t;
6881 uint32_t n;
6882 uint32_t imm32;
6883 bool index;
6884 bool add;
6885 bool wback;
6886
6887 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6888 switch (encoding)
6889 {
6890 case eEncodingT1:
6891 // if Rt == ’1111’ then SEE PLI;
6892 // if Rn == ’1111’ then SEE LDRSB (literal);
6893 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6894 t = Bits32 (opcode, 15, 12);
6895 n = Bits32 (opcode, 19, 16);
6896 imm32 = Bits32 (opcode, 11, 0);
6897
6898 // index = TRUE; add = TRUE; wback = FALSE;
6899 index = true;
6900 add = true;
6901 wback = false;
6902
6903 // if t == 13 then UNPREDICTABLE;
6904 if (t == 13)
6905 return false;
6906
6907 break;
6908
6909 case eEncodingT2:
6910 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6911 // if Rn == ’1111’ then SEE LDRSB (literal);
6912 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6913 // if P == ’0’ && W == ’0’ then UNDEFINED;
6914 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6915 return false;
6916
6917 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6918 t = Bits32 (opcode, 15, 12);
6919 n = Bits32 (opcode, 19, 16);
6920 imm32 = Bits32 (opcode, 7, 0);
6921
6922 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6923 index = BitIsSet (opcode, 10);
6924 add = BitIsSet (opcode, 9);
6925 wback = BitIsSet (opcode, 8);
6926
6927 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6928 if (BadReg (t) || (wback && (n == t)))
6929 return false;
6930
6931 break;
6932
6933 case eEncodingA1:
6934 {
6935 // if Rn == ’1111’ then SEE LDRSB (literal);
6936 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6937 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6938 t = Bits32 (opcode, 15, 12);
6939 n = Bits32 (opcode, 19, 16);
6940
6941 uint32_t imm4H = Bits32 (opcode, 11, 8);
6942 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006943 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006944
6945 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6946 index = BitIsSet (opcode, 24);
6947 add = BitIsSet (opcode, 23);
6948 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6949
6950 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6951 if ((t == 15) || (wback && (n == t)))
6952 return false;
6953
6954 break;
6955 }
6956
6957 default:
6958 return false;
6959 }
6960
6961 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6962 if (!success)
6963 return false;
6964
6965 addr_t offset_addr;
6966 addr_t address;
6967
6968 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6969 if (add)
6970 offset_addr = Rn + imm32;
6971 else
6972 offset_addr = Rn - imm32;
6973
6974 // address = if index then offset_addr else R[n];
6975 if (index)
6976 address = offset_addr;
6977 else
6978 address = Rn;
6979
6980 // R[t] = SignExtend(MemU[address,1], 32);
6981 Register base_reg;
6982 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6983
6984 EmulateInstruction::Context context;
6985 context.type = eContextRegisterLoad;
6986 context.SetRegisterPlusOffset (base_reg, address - Rn);
6987
6988 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6989 if (!success)
6990 return false;
6991
6992 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6993 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6994 return false;
6995
6996 // if wback then R[n] = offset_addr;
6997 if (wback)
6998 {
6999 context.type = eContextAdjustBaseRegister;
7000 context.SetAddress (offset_addr);
7001 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7002 return false;
7003 }
7004 }
7005
7006 return true;
7007}
Caroline Tice0e6bc952011-03-01 18:00:42 +00007008
Caroline Tice5f593912011-03-01 22:25:17 +00007009// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7010// sign-extends it to form a 32-bit word, and writes tit to a register.
7011bool
7012EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
7013{
7014#if 0
7015 if ConditionPassed() then
7016 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7017 base = Align(PC,4);
7018 address = if add then (base + imm32) else (base - imm32);
7019 R[t] = SignExtend(MemU[address,1], 32);
7020#endif
7021
7022 bool success = false;
7023 const uint32_t opcode = OpcodeAsUnsigned (&success);
7024 if (!success)
7025 return false;
7026
7027 if (ConditionPassed ())
7028 {
7029 uint32_t t;
7030 uint32_t imm32;
7031 bool add;
7032
7033 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7034 switch (encoding)
7035 {
7036 case eEncodingT1:
7037 // if Rt == ’1111’ then SEE PLI;
7038 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7039 t = Bits32 (opcode, 15, 12);
7040 imm32 = Bits32 (opcode, 11, 0);
7041 add = BitIsSet (opcode, 23);
7042
7043 // if t == 13 then UNPREDICTABLE;
7044 if (t == 13)
7045 return false;
7046
7047 break;
7048
7049 case eEncodingA1:
7050 {
7051 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7052 t = Bits32 (opcode, 15, 12);
7053 uint32_t imm4H = Bits32 (opcode, 11, 8);
7054 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007055 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007056 add = BitIsSet (opcode, 23);
7057
7058 // if t == 15 then UNPREDICTABLE;
7059 if (t == 15)
7060 return false;
7061
7062 break;
7063 }
7064
7065 default:
7066 return false;
7067 }
7068
7069 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007070 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007071 if (!success)
7072 return false;
7073 uint64_t base = AlignPC (pc_value);
7074
7075 // address = if add then (base + imm32) else (base - imm32);
7076 addr_t address;
7077 if (add)
7078 address = base + imm32;
7079 else
7080 address = base - imm32;
7081
7082 // R[t] = SignExtend(MemU[address,1], 32);
7083 Register base_reg;
7084 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7085
7086 EmulateInstruction::Context context;
7087 context.type = eContextRegisterLoad;
7088 context.SetRegisterPlusOffset (base_reg, address - base);
7089
7090 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7091 if (!success)
7092 return false;
7093
7094 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7095 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7096 return false;
7097 }
7098 return true;
7099}
7100
Caroline Tice672f3112011-03-01 23:55:59 +00007101// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7102// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7103// shifted left by 0, 1, 2, or 3 bits.
7104bool
7105EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
7106{
7107#if 0
7108 if ConditionPassed() then
7109 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7110 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7111 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7112 address = if index then offset_addr else R[n];
7113 R[t] = SignExtend(MemU[address,1], 32);
7114 if wback then R[n] = offset_addr;
7115#endif
7116
7117 bool success = false;
7118 const uint32_t opcode = OpcodeAsUnsigned (&success);
7119 if (!success)
7120 return false;
7121
7122 if (ConditionPassed ())
7123 {
7124 uint32_t t;
7125 uint32_t n;
7126 uint32_t m;
7127 bool index;
7128 bool add;
7129 bool wback;
7130 ARM_ShifterType shift_t;
7131 uint32_t shift_n;
7132
7133 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7134 switch (encoding)
7135 {
7136 case eEncodingT1:
7137 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7138 t = Bits32 (opcode, 2, 0);
7139 n = Bits32 (opcode, 5, 3);
7140 m = Bits32 (opcode, 8, 6);
7141
7142 // index = TRUE; add = TRUE; wback = FALSE;
7143 index = true;
7144 add = true;
7145 wback = false;
7146
7147 // (shift_t, shift_n) = (SRType_LSL, 0);
7148 shift_t = SRType_LSL;
7149 shift_n = 0;
7150
7151 break;
7152
7153 case eEncodingT2:
7154 // if Rt == ’1111’ then SEE PLI;
7155 // if Rn == ’1111’ then SEE LDRSB (literal);
7156 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7157 t = Bits32 (opcode, 15, 12);
7158 n = Bits32 (opcode, 19, 16);
7159 m = Bits32 (opcode, 3, 0);
7160
7161 // index = TRUE; add = TRUE; wback = FALSE;
7162 index = true;
7163 add = true;
7164 wback = false;
7165
7166 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7167 shift_t = SRType_LSL;
7168 shift_n = Bits32 (opcode, 5, 4);
7169
7170 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7171 if ((t == 13) || BadReg (m))
7172 return false;
7173 break;
7174
7175 case eEncodingA1:
7176 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
7177 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7178 t = Bits32 (opcode, 15, 12);
7179 n = Bits32 (opcode, 19, 16);
7180 m = Bits32 (opcode, 3, 0);
7181
7182 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7183 index = BitIsSet (opcode, 24);
7184 add = BitIsSet (opcode, 23);
7185 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7186
7187 // (shift_t, shift_n) = (SRType_LSL, 0);
7188 shift_t = SRType_LSL;
7189 shift_n = 0;
7190
7191 // if t == 15 || m == 15 then UNPREDICTABLE;
7192 if ((t == 15) || (m == 15))
7193 return false;
7194
7195 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7196 if (wback && ((n == 15) || (n == t)))
7197 return false;
7198 break;
7199
7200 default:
7201 return false;
7202 }
7203
7204 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7205 if (!success)
7206 return false;
7207
7208 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7209 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7210
7211 addr_t offset_addr;
7212 addr_t address;
7213
7214 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7215 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7216 if (!success)
7217 return false;
7218
7219 if (add)
7220 offset_addr = Rn + offset;
7221 else
7222 offset_addr = Rn - offset;
7223
7224 // address = if index then offset_addr else R[n];
7225 if (index)
7226 address = offset_addr;
7227 else
7228 address = Rn;
7229
7230 // R[t] = SignExtend(MemU[address,1], 32);
7231 Register base_reg;
7232 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7233 Register offset_reg;
7234 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7235
7236 EmulateInstruction::Context context;
7237 context.type = eContextRegisterLoad;
7238 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7239
7240 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7241 if (!success)
7242 return false;
7243
7244 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7245 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7246 return false;
7247
7248 // if wback then R[n] = offset_addr;
7249 if (wback)
7250 {
7251 context.type = eContextAdjustBaseRegister;
7252 context.SetAddress (offset_addr);
7253 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7254 return false;
7255 }
7256 }
7257 return true;
7258}
7259
Caroline Tice78fb5632011-03-02 00:39:42 +00007260// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7261// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7262// pre-indexed addressing.
7263bool
7264EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
7265{
7266#if 0
7267 if ConditionPassed() then
7268 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7269 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7270 address = if index then offset_addr else R[n];
7271 data = MemU[address,2];
7272 if wback then R[n] = offset_addr;
7273 if UnalignedSupport() || address<0> = ’0’ then
7274 R[t] = SignExtend(data, 32);
7275 else // Can only apply before ARMv7
7276 R[t] = bits(32) UNKNOWN;
7277#endif
7278
7279 bool success = false;
7280 const uint32_t opcode = OpcodeAsUnsigned (&success);
7281 if (!success)
7282 return false;
7283
7284 if (ConditionPassed())
7285 {
7286 uint32_t t;
7287 uint32_t n;
7288 uint32_t imm32;
7289 bool index;
7290 bool add;
7291 bool wback;
7292
7293 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7294 switch (encoding)
7295 {
7296 case eEncodingT1:
7297 // if Rn == ’1111’ then SEE LDRSH (literal);
7298 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7299 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7300 t = Bits32 (opcode, 15, 12);
7301 n = Bits32 (opcode, 19, 16);
7302 imm32 = Bits32 (opcode, 11, 0);
7303
7304 // index = TRUE; add = TRUE; wback = FALSE;
7305 index = true;
7306 add = true;
7307 wback = false;
7308
7309 // if t == 13 then UNPREDICTABLE;
7310 if (t == 13)
7311 return false;
7312
7313 break;
7314
7315 case eEncodingT2:
7316 // if Rn == ’1111’ then SEE LDRSH (literal);
7317 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7318 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7319 // if P == ’0’ && W == ’0’ then UNDEFINED;
7320 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7321 return false;
7322
7323 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7324 t = Bits32 (opcode, 15, 12);
7325 n = Bits32 (opcode, 19, 16);
7326 imm32 = Bits32 (opcode, 7, 0);
7327
7328 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7329 index = BitIsSet (opcode, 10);
7330 add = BitIsSet (opcode, 9);
7331 wback = BitIsSet (opcode, 8);
7332
7333 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7334 if (BadReg (t) || (wback && (n == t)))
7335 return false;
7336
7337 break;
7338
7339 case eEncodingA1:
7340 {
7341 // if Rn == ’1111’ then SEE LDRSH (literal);
7342 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7343 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7344 t = Bits32 (opcode, 15, 12);
7345 n = Bits32 (opcode, 19, 16);
7346 uint32_t imm4H = Bits32 (opcode, 11,8);
7347 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007348 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007349
7350 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7351 index = BitIsSet (opcode, 24);
7352 add = BitIsSet (opcode, 23);
7353 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7354
7355 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7356 if ((t == 15) || (wback && (n == t)))
7357 return false;
7358
7359 break;
7360 }
7361
7362 default:
7363 return false;
7364 }
7365
7366 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7367 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7368 if (!success)
7369 return false;
7370
7371 addr_t offset_addr;
7372 if (add)
7373 offset_addr = Rn + imm32;
7374 else
7375 offset_addr = Rn - imm32;
7376
7377 // address = if index then offset_addr else R[n];
7378 addr_t address;
7379 if (index)
7380 address = offset_addr;
7381 else
7382 address = Rn;
7383
7384 // data = MemU[address,2];
7385 Register base_reg;
7386 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7387
7388 EmulateInstruction::Context context;
7389 context.type = eContextRegisterLoad;
7390 context.SetRegisterPlusOffset (base_reg, address - Rn);
7391
7392 uint64_t data = MemURead (context, address, 2, 0, &success);
7393 if (!success)
7394 return false;
7395
7396 // if wback then R[n] = offset_addr;
7397 if (wback)
7398 {
7399 context.type = eContextAdjustBaseRegister;
7400 context.SetAddress (offset_addr);
7401 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7402 return false;
7403 }
7404
7405 // if UnalignedSupport() || address<0> = ’0’ then
7406 if (UnalignedSupport() || BitIsClear (address, 0))
7407 {
7408 // R[t] = SignExtend(data, 32);
7409 int64_t signed_data = llvm::SignExtend64<16>(data);
7410 context.type = eContextRegisterLoad;
7411 context.SetRegisterPlusOffset (base_reg, address - Rn);
7412 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7413 return false;
7414 }
7415 else // Can only apply before ARMv7
7416 {
7417 // R[t] = bits(32) UNKNOWN;
7418 WriteBits32Unknown (t);
7419 }
7420 }
7421 return true;
7422}
7423
Caroline Ticed2fac092011-03-02 19:45:34 +00007424// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7425// sign-extends it to from a 32-bit word, and writes it to a register.
7426bool
7427EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7428{
7429#if 0
7430 if ConditionPassed() then
7431 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7432 base = Align(PC,4);
7433 address = if add then (base + imm32) else (base - imm32);
7434 data = MemU[address,2];
7435 if UnalignedSupport() || address<0> = ’0’ then
7436 R[t] = SignExtend(data, 32);
7437 else // Can only apply before ARMv7
7438 R[t] = bits(32) UNKNOWN;
7439#endif
7440
7441 bool success = false;
7442 const uint32_t opcode = OpcodeAsUnsigned (&success);
7443 if (!success)
7444 return false;
7445
7446 if (ConditionPassed())
7447 {
7448 uint32_t t;
7449 uint32_t imm32;
7450 bool add;
7451
7452 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7453 switch (encoding)
7454 {
7455 case eEncodingT1:
7456 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7457 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7458 t = Bits32 (opcode, 15, 12);
7459 imm32 = Bits32 (opcode, 11, 0);
7460 add = BitIsSet (opcode, 23);
7461
7462 // if t == 13 then UNPREDICTABLE;
7463 if (t == 13)
7464 return false;
7465
7466 break;
7467
7468 case eEncodingA1:
7469 {
7470 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7471 t = Bits32 (opcode, 15, 12);
7472 uint32_t imm4H = Bits32 (opcode, 11, 8);
7473 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007474 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007475 add = BitIsSet (opcode, 23);
7476
7477 // if t == 15 then UNPREDICTABLE;
7478 if (t == 15)
7479 return false;
7480
7481 break;
7482 }
7483 default:
7484 return false;
7485 }
7486
7487 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007488 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007489 if (!success)
7490 return false;
7491
7492 uint64_t base = AlignPC (pc_value);
7493
7494 addr_t address;
7495 // address = if add then (base + imm32) else (base - imm32);
7496 if (add)
7497 address = base + imm32;
7498 else
7499 address = base - imm32;
7500
7501 // data = MemU[address,2];
7502 Register base_reg;
7503 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7504
7505 EmulateInstruction::Context context;
7506 context.type = eContextRegisterLoad;
7507 context.SetRegisterPlusOffset (base_reg, imm32);
7508
7509 uint64_t data = MemURead (context, address, 2, 0, &success);
7510 if (!success)
7511 return false;
7512
7513 // if UnalignedSupport() || address<0> = ’0’ then
7514 if (UnalignedSupport() || BitIsClear (address, 0))
7515 {
7516 // R[t] = SignExtend(data, 32);
7517 int64_t signed_data = llvm::SignExtend64<16>(data);
7518 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7519 return false;
7520 }
7521 else // Can only apply before ARMv7
7522 {
7523 // R[t] = bits(32) UNKNOWN;
7524 WriteBits32Unknown (t);
7525 }
7526 }
7527 return true;
7528}
7529
Caroline Tice291a3e92011-03-02 21:13:44 +00007530// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7531// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7532// shifted left by 0, 1, 2, or 3 bits.
7533bool
7534EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7535{
7536#if 0
7537 if ConditionPassed() then
7538 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7539 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7540 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7541 address = if index then offset_addr else R[n];
7542 data = MemU[address,2];
7543 if wback then R[n] = offset_addr;
7544 if UnalignedSupport() || address<0> = ’0’ then
7545 R[t] = SignExtend(data, 32);
7546 else // Can only apply before ARMv7
7547 R[t] = bits(32) UNKNOWN;
7548#endif
7549
7550 bool success = false;
7551 const uint32_t opcode = OpcodeAsUnsigned (&success);
7552 if (!success)
7553 return false;
7554
7555 if (ConditionPassed())
7556 {
7557 uint32_t t;
7558 uint32_t n;
7559 uint32_t m;
7560 bool index;
7561 bool add;
7562 bool wback;
7563 ARM_ShifterType shift_t;
7564 uint32_t shift_n;
7565
7566 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7567 switch (encoding)
7568 {
7569 case eEncodingT1:
7570 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7571 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7572 t = Bits32 (opcode, 2, 0);
7573 n = Bits32 (opcode, 5, 3);
7574 m = Bits32 (opcode, 8, 6);
7575
7576 // index = TRUE; add = TRUE; wback = FALSE;
7577 index = true;
7578 add = true;
7579 wback = false;
7580
7581 // (shift_t, shift_n) = (SRType_LSL, 0);
7582 shift_t = SRType_LSL;
7583 shift_n = 0;
7584
7585 break;
7586
7587 case eEncodingT2:
7588 // if Rn == ’1111’ then SEE LDRSH (literal);
7589 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7590 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7591 t = Bits32 (opcode, 15, 12);
7592 n = Bits32 (opcode, 19, 16);
7593 m = Bits32 (opcode, 3, 0);
7594
7595 // index = TRUE; add = TRUE; wback = FALSE;
7596 index = true;
7597 add = true;
7598 wback = false;
7599
7600 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7601 shift_t = SRType_LSL;
7602 shift_n = Bits32 (opcode, 5, 4);
7603
7604 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7605 if ((t == 13) || BadReg (m))
7606 return false;
7607
7608 break;
7609
7610 case eEncodingA1:
7611 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7612 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7613 t = Bits32 (opcode, 15, 12);
7614 n = Bits32 (opcode, 19, 16);
7615 m = Bits32 (opcode, 3, 0);
7616
7617 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7618 index = BitIsSet (opcode, 24);
7619 add = BitIsSet (opcode, 23);
7620 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7621
7622 // (shift_t, shift_n) = (SRType_LSL, 0);
7623 shift_t = SRType_LSL;
7624 shift_n = 0;
7625
7626 // if t == 15 || m == 15 then UNPREDICTABLE;
7627 if ((t == 15) || (m == 15))
7628 return false;
7629
7630 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7631 if (wback && ((n == 15) || (n == t)))
7632 return false;
7633
7634 break;
7635
7636 default:
7637 break;
7638 }
7639
7640 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7641 if (!success)
7642 return false;
7643
7644 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7645 if (!success)
7646 return false;
7647
7648 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7649 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7650
7651 addr_t offset_addr;
7652 addr_t address;
7653
7654 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7655 if (add)
7656 offset_addr = Rn + offset;
7657 else
7658 offset_addr = Rn - offset;
7659
7660 // address = if index then offset_addr else R[n];
7661 if (index)
7662 address = offset_addr;
7663 else
7664 address = Rn;
7665
7666 // data = MemU[address,2];
7667 Register base_reg;
7668 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7669
7670 Register offset_reg;
7671 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7672
7673 EmulateInstruction::Context context;
7674 context.type = eContextRegisterLoad;
7675 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7676
7677 uint64_t data = MemURead (context, address, 2, 0, &success);
7678 if (!success)
7679 return false;
7680
7681 // if wback then R[n] = offset_addr;
7682 if (wback)
7683 {
7684 context.type = eContextAdjustBaseRegister;
7685 context.SetAddress (offset_addr);
7686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7687 return false;
7688 }
7689
7690 // if UnalignedSupport() || address<0> = ’0’ then
7691 if (UnalignedSupport() || BitIsClear (address, 0))
7692 {
7693 // R[t] = SignExtend(data, 32);
7694 context.type = eContextRegisterLoad;
7695 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7696
7697 int64_t signed_data = llvm::SignExtend64<16>(data);
7698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7699 return false;
7700 }
7701 else // Can only apply before ARMv7
7702 {
7703 // R[t] = bits(32) UNKNOWN;
7704 WriteBits32Unknown (t);
7705 }
7706 }
7707 return true;
7708}
Caroline Tice6bf65162011-03-03 17:42:58 +00007709
7710// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7711// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7712bool
7713EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7714{
7715#if 0
7716 if ConditionPassed() then
7717 EncodingSpecificOperations();
7718 rotated = ROR(R[m], rotation);
7719 R[d] = SignExtend(rotated<7:0>, 32);
7720#endif
7721
7722 bool success = false;
7723 const uint32_t opcode = OpcodeAsUnsigned (&success);
7724 if (!success)
7725 return false;
7726
7727 if (ConditionPassed())
7728 {
7729 uint32_t d;
7730 uint32_t m;
7731 uint32_t rotation;
7732
7733 // EncodingSpecificOperations();
7734 switch (encoding)
7735 {
7736 case eEncodingT1:
7737 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7738 d = Bits32 (opcode, 2, 0);
7739 m = Bits32 (opcode, 5, 3);
7740 rotation = 0;
7741
7742 break;
7743
7744 case eEncodingT2:
7745 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7746 d = Bits32 (opcode, 11, 8);
7747 m = Bits32 (opcode, 3, 0);
7748 rotation = Bits32 (opcode, 5, 4) << 3;
7749
7750 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7751 if (BadReg (d) || BadReg (m))
7752 return false;
7753
7754 break;
7755
7756 case eEncodingA1:
7757 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7758 d = Bits32 (opcode, 15, 12);
7759 m = Bits32 (opcode, 3, 0);
7760 rotation = Bits32 (opcode, 11, 10) << 3;
7761
7762 // if d == 15 || m == 15 then UNPREDICTABLE;
7763 if ((d == 15) || (m == 15))
7764 return false;
7765
7766 break;
7767
7768 default:
7769 return false;
7770 }
7771
Caroline Tice868198b2011-03-03 18:04:49 +00007772 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7773 if (!success)
7774 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007775
7776 // rotated = ROR(R[m], rotation);
7777 uint64_t rotated = ROR (Rm, rotation);
7778
7779 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007780 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007781
7782 Register source_reg;
7783 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7784
7785 EmulateInstruction::Context context;
7786 context.type = eContextRegisterLoad;
7787 context.SetRegister (source_reg);
7788
Caroline Tice8ce96d92011-03-03 18:27:17 +00007789 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007790 return false;
7791 }
7792 return true;
7793}
Caroline Tice291a3e92011-03-02 21:13:44 +00007794
Caroline Tice868198b2011-03-03 18:04:49 +00007795// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7796// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7797bool
7798EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7799{
7800#if 0
7801 if ConditionPassed() then
7802 EncodingSpecificOperations();
7803 rotated = ROR(R[m], rotation);
7804 R[d] = SignExtend(rotated<15:0>, 32);
7805#endif
7806
7807 bool success = false;
7808 const uint32_t opcode = OpcodeAsUnsigned (&success);
7809 if (!success)
7810 return false;
7811
7812 if (ConditionPassed())
7813 {
7814 uint32_t d;
7815 uint32_t m;
7816 uint32_t rotation;
7817
7818 // EncodingSpecificOperations();
7819 switch (encoding)
7820 {
7821 case eEncodingT1:
7822 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7823 d = Bits32 (opcode, 2, 0);
7824 m = Bits32 (opcode, 5, 3);
7825 rotation = 0;
7826
7827 break;
7828
7829 case eEncodingT2:
7830 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7831 d = Bits32 (opcode, 11, 8);
7832 m = Bits32 (opcode, 3, 0);
7833 rotation = Bits32 (opcode, 5, 4) << 3;
7834
7835 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7836 if (BadReg (d) || BadReg (m))
7837 return false;
7838
7839 break;
7840
7841 case eEncodingA1:
7842 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7843 d = Bits32 (opcode, 15, 12);
7844 m = Bits32 (opcode, 3, 0);
7845 rotation = Bits32 (opcode, 11, 10) << 3;
7846
7847 // if d == 15 || m == 15 then UNPREDICTABLE;
7848 if ((d == 15) || (m == 15))
7849 return false;
7850
7851 break;
7852
7853 default:
7854 return false;
7855 }
7856
7857 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7858 if (!success)
7859 return false;
7860
7861 // rotated = ROR(R[m], rotation);
7862 uint64_t rotated = ROR (Rm, rotation);
7863
7864 // R[d] = SignExtend(rotated<15:0>, 32);
7865 Register source_reg;
7866 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7867
7868 EmulateInstruction::Context context;
7869 context.type = eContextRegisterLoad;
7870 context.SetRegister (source_reg);
7871
Caroline Tice8ce96d92011-03-03 18:27:17 +00007872 int64_t data = llvm::SignExtend64<16> (rotated);
7873 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007874 return false;
7875 }
7876
7877 return true;
7878}
7879
Caroline Tice8ce96d92011-03-03 18:27:17 +00007880// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7881// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7882bool
7883EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7884{
7885#if 0
7886 if ConditionPassed() then
7887 EncodingSpecificOperations();
7888 rotated = ROR(R[m], rotation);
7889 R[d] = ZeroExtend(rotated<7:0>, 32);
7890#endif
7891
7892 bool success = false;
7893 const uint32_t opcode = OpcodeAsUnsigned (&success);
7894 if (!success)
7895 return false;
7896
7897 if (ConditionPassed())
7898 {
7899 uint32_t d;
7900 uint32_t m;
7901 uint32_t rotation;
7902
7903 // EncodingSpecificOperations();
7904 switch (encoding)
7905 {
7906 case eEncodingT1:
7907 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7908 d = Bits32 (opcode, 2, 0);
7909 m = Bits32 (opcode, 5, 3);
7910 rotation = 0;
7911
7912 break;
7913
7914 case eEncodingT2:
7915 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7916 d = Bits32 (opcode, 11, 8);
7917 m = Bits32 (opcode, 3, 0);
7918 rotation = Bits32 (opcode, 5, 4) << 3;
7919
7920 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7921 if (BadReg (d) || BadReg (m))
7922 return false;
7923
7924 break;
7925
7926 case eEncodingA1:
7927 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7928 d = Bits32 (opcode, 15, 12);
7929 m = Bits32 (opcode, 3, 0);
7930 rotation = Bits32 (opcode, 11, 10) << 3;
7931
7932 // if d == 15 || m == 15 then UNPREDICTABLE;
7933 if ((d == 15) || (m == 15))
7934 return false;
7935
7936 break;
7937
7938 default:
7939 return false;
7940 }
7941
7942 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7943 if (!success)
7944 return false;
7945
7946 // rotated = ROR(R[m], rotation);
7947 uint64_t rotated = ROR (Rm, rotation);
7948
7949 // R[d] = ZeroExtend(rotated<7:0>, 32);
7950 Register source_reg;
7951 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7952
7953 EmulateInstruction::Context context;
7954 context.type = eContextRegisterLoad;
7955 context.SetRegister (source_reg);
7956
7957 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7958 return false;
7959 }
7960 return true;
7961}
7962
Caroline Tice11555f22011-03-03 18:48:58 +00007963// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7964// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7965bool
7966EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7967{
7968#if 0
7969 if ConditionPassed() then
7970 EncodingSpecificOperations();
7971 rotated = ROR(R[m], rotation);
7972 R[d] = ZeroExtend(rotated<15:0>, 32);
7973#endif
7974
7975 bool success = false;
7976 const uint32_t opcode = OpcodeAsUnsigned (&success);
7977 if (!success)
7978 return false;
7979
7980 if (ConditionPassed ())
7981 {
7982 uint32_t d;
7983 uint32_t m;
7984 uint32_t rotation;
7985
7986 switch (encoding)
7987 {
7988 case eEncodingT1:
7989 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7990 d = Bits32 (opcode, 2, 0);
7991 m = Bits32 (opcode, 5, 3);
7992 rotation = 0;
7993
7994 break;
7995
7996 case eEncodingT2:
7997 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7998 d = Bits32 (opcode, 11, 8);
7999 m = Bits32 (opcode, 3, 0);
8000 rotation = Bits32 (opcode, 5, 4) << 3;
8001
8002 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8003 if (BadReg (d) || BadReg (m))
8004 return false;
8005
8006 break;
8007
8008 case eEncodingA1:
8009 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
8010 d = Bits32 (opcode, 15, 12);
8011 m = Bits32 (opcode, 3, 0);
8012 rotation = Bits32 (opcode, 11, 10) << 3;
8013
8014 // if d == 15 || m == 15 then UNPREDICTABLE;
8015 if ((d == 15) || (m == 15))
8016 return false;
8017
8018 break;
8019
8020 default:
8021 return false;
8022 }
8023
8024 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8025 if (!success)
8026 return false;
8027
8028 // rotated = ROR(R[m], rotation);
8029 uint64_t rotated = ROR (Rm, rotation);
8030
8031 // R[d] = ZeroExtend(rotated<15:0>, 32);
8032 Register source_reg;
8033 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
8034
8035 EmulateInstruction::Context context;
8036 context.type = eContextRegisterLoad;
8037 context.SetRegister (source_reg);
8038
8039 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8040 return false;
8041 }
8042 return true;
8043}
Caroline Ticeb27771d2011-03-03 22:37:46 +00008044
8045// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8046// word respectively.
8047bool
8048EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
8049{
8050#if 0
8051 if ConditionPassed() then
8052 EncodingSpecificOperations();
8053 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8054 UNPREDICTABLE;
8055 else
8056 address = if increment then R[n] else R[n]-8;
8057 if wordhigher then address = address+4;
8058 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8059 BranchWritePC(MemA[address,4]);
8060 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8061#endif
8062
8063 bool success = false;
8064 const uint32_t opcode = OpcodeAsUnsigned (&success);
8065 if (!success)
8066 return false;
8067
8068 if (ConditionPassed())
8069 {
8070 uint32_t n;
8071 bool wback;
8072 bool increment;
8073 bool wordhigher;
8074
8075 // EncodingSpecificOperations();
8076 switch (encoding)
8077 {
8078 case eEncodingT1:
8079 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
8080 n = Bits32 (opcode, 19, 16);
8081 wback = BitIsSet (opcode, 21);
8082 increment = false;
8083 wordhigher = false;
8084
8085 // if n == 15 then UNPREDICTABLE;
8086 if (n == 15)
8087 return false;
8088
8089 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8090 if (InITBlock() && !LastInITBlock())
8091 return false;
8092
8093 break;
8094
8095 case eEncodingT2:
8096 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
8097 n = Bits32 (opcode, 19, 16);
8098 wback = BitIsSet (opcode, 21);
8099 increment = true;
8100 wordhigher = false;
8101
8102 // if n == 15 then UNPREDICTABLE;
8103 if (n == 15)
8104 return false;
8105
8106 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8107 if (InITBlock() && !LastInITBlock())
8108 return false;
8109
8110 break;
8111
8112 case eEncodingA1:
8113 // n = UInt(Rn);
8114 n = Bits32 (opcode, 19, 16);
8115
8116 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
8117 wback = BitIsSet (opcode, 21);
8118 increment = BitIsSet (opcode, 23);
8119 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8120
8121 // if n == 15 then UNPREDICTABLE;
8122 if (n == 15)
8123 return false;
8124
8125 break;
8126
8127 default:
8128 return false;
8129 }
8130
8131 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8132 if (!CurrentModeIsPrivileged ())
8133 // UNPREDICTABLE;
8134 return false;
8135 else
8136 {
8137 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8138 if (!success)
8139 return false;
8140
8141 addr_t address;
8142 // address = if increment then R[n] else R[n]-8;
8143 if (increment)
8144 address = Rn;
8145 else
8146 address = Rn - 8;
8147
8148 // if wordhigher then address = address+4;
8149 if (wordhigher)
8150 address = address + 4;
8151
8152 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8153 Register base_reg;
8154 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8155
8156 EmulateInstruction::Context context;
8157 context.type = eContextReturnFromException;
8158 context.SetRegisterPlusOffset (base_reg, address - Rn);
8159
8160 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8161 if (!success)
8162 return false;
8163
8164 CPSRWriteByInstr (data, 15, true);
8165
8166 // BranchWritePC(MemA[address,4]);
8167 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8168 if (!success)
8169 return false;
8170
8171 BranchWritePC (context, data2);
8172
8173 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8174 if (wback)
8175 {
8176 context.type = eContextAdjustBaseRegister;
8177 if (increment)
8178 {
8179 context.SetOffset (8);
8180 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8181 return false;
8182 }
8183 else
8184 {
8185 context.SetOffset (-8);
8186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8187 return false;
8188 }
8189 } // if wback
8190 }
8191 } // if ConditionPassed()
8192 return true;
8193}
Caroline Tice11555f22011-03-03 18:48:58 +00008194
Johnny Chen2115b412011-02-21 23:42:44 +00008195// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8196// and writes the result to the destination register. It can optionally update the condition flags based on
8197// the result.
8198bool
8199EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
8200{
8201#if 0
8202 // ARM pseudo code...
8203 if ConditionPassed() then
8204 EncodingSpecificOperations();
8205 result = R[n] EOR imm32;
8206 if d == 15 then // Can only occur for ARM encoding
8207 ALUWritePC(result); // setflags is always FALSE here
8208 else
8209 R[d] = result;
8210 if setflags then
8211 APSR.N = result<31>;
8212 APSR.Z = IsZeroBit(result);
8213 APSR.C = carry;
8214 // APSR.V unchanged
8215#endif
8216
8217 bool success = false;
8218 const uint32_t opcode = OpcodeAsUnsigned (&success);
8219 if (!success)
8220 return false;
8221
8222 if (ConditionPassed())
8223 {
8224 uint32_t Rd, Rn;
8225 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8226 bool setflags;
8227 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8228 switch (encoding)
8229 {
8230 case eEncodingT1:
8231 Rd = Bits32(opcode, 11, 8);
8232 Rn = Bits32(opcode, 19, 16);
8233 setflags = BitIsSet(opcode, 20);
8234 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8235 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8236 if (Rd == 15 && setflags)
8237 return EmulateTEQImm(eEncodingT1);
8238 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8239 return false;
8240 break;
8241 case eEncodingA1:
8242 Rd = Bits32(opcode, 15, 12);
8243 Rn = Bits32(opcode, 19, 16);
8244 setflags = BitIsSet(opcode, 20);
8245 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8246 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8247 // TODO: Emulate SUBS PC, LR and related instructions.
8248 if (Rd == 15 && setflags)
8249 return false;
8250 break;
8251 default:
8252 return false;
8253 }
8254
8255 // Read the first operand.
8256 uint32_t val1 = ReadCoreReg(Rn, &success);
8257 if (!success)
8258 return false;
8259
8260 uint32_t result = val1 ^ imm32;
8261
8262 EmulateInstruction::Context context;
8263 context.type = EmulateInstruction::eContextImmediate;
8264 context.SetNoArgs ();
8265
8266 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8267 return false;
8268 }
8269 return true;
8270}
8271
8272// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8273// optionally-shifted register value, and writes the result to the destination register.
8274// It can optionally update the condition flags based on the result.
8275bool
8276EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
8277{
8278#if 0
8279 // ARM pseudo code...
8280 if ConditionPassed() then
8281 EncodingSpecificOperations();
8282 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8283 result = R[n] EOR shifted;
8284 if d == 15 then // Can only occur for ARM encoding
8285 ALUWritePC(result); // setflags is always FALSE here
8286 else
8287 R[d] = result;
8288 if setflags then
8289 APSR.N = result<31>;
8290 APSR.Z = IsZeroBit(result);
8291 APSR.C = carry;
8292 // APSR.V unchanged
8293#endif
8294
8295 bool success = false;
8296 const uint32_t opcode = OpcodeAsUnsigned (&success);
8297 if (!success)
8298 return false;
8299
8300 if (ConditionPassed())
8301 {
8302 uint32_t Rd, Rn, Rm;
8303 ARM_ShifterType shift_t;
8304 uint32_t shift_n; // the shift applied to the value read from Rm
8305 bool setflags;
8306 uint32_t carry;
8307 switch (encoding)
8308 {
8309 case eEncodingT1:
8310 Rd = Rn = Bits32(opcode, 2, 0);
8311 Rm = Bits32(opcode, 5, 3);
8312 setflags = !InITBlock();
8313 shift_t = SRType_LSL;
8314 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008315 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008316 case eEncodingT2:
8317 Rd = Bits32(opcode, 11, 8);
8318 Rn = Bits32(opcode, 19, 16);
8319 Rm = Bits32(opcode, 3, 0);
8320 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008321 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8322 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008323 if (Rd == 15 && setflags)
8324 return EmulateTEQReg(eEncodingT1);
8325 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8326 return false;
8327 break;
8328 case eEncodingA1:
8329 Rd = Bits32(opcode, 15, 12);
8330 Rn = Bits32(opcode, 19, 16);
8331 Rm = Bits32(opcode, 3, 0);
8332 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008333 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008334 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8335 // TODO: Emulate SUBS PC, LR and related instructions.
8336 if (Rd == 15 && setflags)
8337 return false;
8338 break;
8339 default:
8340 return false;
8341 }
8342
8343 // Read the first operand.
8344 uint32_t val1 = ReadCoreReg(Rn, &success);
8345 if (!success)
8346 return false;
8347
8348 // Read the second operand.
8349 uint32_t val2 = ReadCoreReg(Rm, &success);
8350 if (!success)
8351 return false;
8352
8353 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8354 uint32_t result = val1 ^ shifted;
8355
8356 EmulateInstruction::Context context;
8357 context.type = EmulateInstruction::eContextImmediate;
8358 context.SetNoArgs ();
8359
8360 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8361 return false;
8362 }
8363 return true;
8364}
8365
Johnny Chen7c5234d2011-02-18 23:41:11 +00008366// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8367// writes the result to the destination register. It can optionally update the condition flags based
8368// on the result.
8369bool
8370EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8371{
8372#if 0
8373 // ARM pseudo code...
8374 if ConditionPassed() then
8375 EncodingSpecificOperations();
8376 result = R[n] OR imm32;
8377 if d == 15 then // Can only occur for ARM encoding
8378 ALUWritePC(result); // setflags is always FALSE here
8379 else
8380 R[d] = result;
8381 if setflags then
8382 APSR.N = result<31>;
8383 APSR.Z = IsZeroBit(result);
8384 APSR.C = carry;
8385 // APSR.V unchanged
8386#endif
8387
8388 bool success = false;
8389 const uint32_t opcode = OpcodeAsUnsigned (&success);
8390 if (!success)
8391 return false;
8392
8393 if (ConditionPassed())
8394 {
8395 uint32_t Rd, Rn;
8396 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8397 bool setflags;
8398 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8399 switch (encoding)
8400 {
8401 case eEncodingT1:
8402 Rd = Bits32(opcode, 11, 8);
8403 Rn = Bits32(opcode, 19, 16);
8404 setflags = BitIsSet(opcode, 20);
8405 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8406 // if Rn == ‘1111’ then SEE MOV (immediate);
8407 if (Rn == 15)
8408 return EmulateMOVRdImm(eEncodingT2);
8409 if (BadReg(Rd) || Rn == 13)
8410 return false;
8411 break;
8412 case eEncodingA1:
8413 Rd = Bits32(opcode, 15, 12);
8414 Rn = Bits32(opcode, 19, 16);
8415 setflags = BitIsSet(opcode, 20);
8416 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8417 // TODO: Emulate SUBS PC, LR and related instructions.
8418 if (Rd == 15 && setflags)
8419 return false;
8420 break;
8421 default:
8422 return false;
8423 }
8424
8425 // Read the first operand.
8426 uint32_t val1 = ReadCoreReg(Rn, &success);
8427 if (!success)
8428 return false;
8429
8430 uint32_t result = val1 | imm32;
8431
8432 EmulateInstruction::Context context;
8433 context.type = EmulateInstruction::eContextImmediate;
8434 context.SetNoArgs ();
8435
8436 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8437 return false;
8438 }
8439 return true;
8440}
8441
8442// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8443// value, and writes the result to the destination register. It can optionally update the condition flags based
8444// on the result.
8445bool
8446EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8447{
8448#if 0
8449 // ARM pseudo code...
8450 if ConditionPassed() then
8451 EncodingSpecificOperations();
8452 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8453 result = R[n] OR shifted;
8454 if d == 15 then // Can only occur for ARM encoding
8455 ALUWritePC(result); // setflags is always FALSE here
8456 else
8457 R[d] = result;
8458 if setflags then
8459 APSR.N = result<31>;
8460 APSR.Z = IsZeroBit(result);
8461 APSR.C = carry;
8462 // APSR.V unchanged
8463#endif
8464
8465 bool success = false;
8466 const uint32_t opcode = OpcodeAsUnsigned (&success);
8467 if (!success)
8468 return false;
8469
8470 if (ConditionPassed())
8471 {
8472 uint32_t Rd, Rn, Rm;
8473 ARM_ShifterType shift_t;
8474 uint32_t shift_n; // the shift applied to the value read from Rm
8475 bool setflags;
8476 uint32_t carry;
8477 switch (encoding)
8478 {
8479 case eEncodingT1:
8480 Rd = Rn = Bits32(opcode, 2, 0);
8481 Rm = Bits32(opcode, 5, 3);
8482 setflags = !InITBlock();
8483 shift_t = SRType_LSL;
8484 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008485 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008486 case eEncodingT2:
8487 Rd = Bits32(opcode, 11, 8);
8488 Rn = Bits32(opcode, 19, 16);
8489 Rm = Bits32(opcode, 3, 0);
8490 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008491 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8492 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008493 if (Rn == 15)
8494 return EmulateMOVRdRm(eEncodingT3);
8495 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8496 return false;
8497 break;
8498 case eEncodingA1:
8499 Rd = Bits32(opcode, 15, 12);
8500 Rn = Bits32(opcode, 19, 16);
8501 Rm = Bits32(opcode, 3, 0);
8502 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008503 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008504 // TODO: Emulate SUBS PC, LR and related instructions.
8505 if (Rd == 15 && setflags)
8506 return false;
8507 break;
8508 default:
8509 return false;
8510 }
8511
8512 // Read the first operand.
8513 uint32_t val1 = ReadCoreReg(Rn, &success);
8514 if (!success)
8515 return false;
8516
8517 // Read the second operand.
8518 uint32_t val2 = ReadCoreReg(Rm, &success);
8519 if (!success)
8520 return false;
8521
8522 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008523 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008524
8525 EmulateInstruction::Context context;
8526 context.type = EmulateInstruction::eContextImmediate;
8527 context.SetNoArgs ();
8528
8529 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8530 return false;
8531 }
8532 return true;
8533}
8534
Johnny Chened32e7c2011-02-22 23:42:58 +00008535// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8536// the destination register. It can optionally update the condition flags based on the result.
8537bool
8538EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8539{
8540#if 0
8541 // ARM pseudo code...
8542 if ConditionPassed() then
8543 EncodingSpecificOperations();
8544 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8545 if d == 15 then // Can only occur for ARM encoding
8546 ALUWritePC(result); // setflags is always FALSE here
8547 else
8548 R[d] = result;
8549 if setflags then
8550 APSR.N = result<31>;
8551 APSR.Z = IsZeroBit(result);
8552 APSR.C = carry;
8553 APSR.V = overflow;
8554#endif
8555
8556 bool success = false;
8557 const uint32_t opcode = OpcodeAsUnsigned (&success);
8558 if (!success)
8559 return false;
8560
8561 uint32_t Rd; // the destination register
8562 uint32_t Rn; // the first operand
8563 bool setflags;
8564 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8565 switch (encoding) {
8566 case eEncodingT1:
8567 Rd = Bits32(opcode, 2, 0);
8568 Rn = Bits32(opcode, 5, 3);
8569 setflags = !InITBlock();
8570 imm32 = 0;
8571 break;
8572 case eEncodingT2:
8573 Rd = Bits32(opcode, 11, 8);
8574 Rn = Bits32(opcode, 19, 16);
8575 setflags = BitIsSet(opcode, 20);
8576 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8577 if (BadReg(Rd) || BadReg(Rn))
8578 return false;
8579 break;
8580 case eEncodingA1:
8581 Rd = Bits32(opcode, 15, 12);
8582 Rn = Bits32(opcode, 19, 16);
8583 setflags = BitIsSet(opcode, 20);
8584 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8585 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8586 // TODO: Emulate SUBS PC, LR and related instructions.
8587 if (Rd == 15 && setflags)
8588 return false;
8589 break;
8590 default:
8591 return false;
8592 }
8593 // Read the register value from the operand register Rn.
8594 uint32_t reg_val = ReadCoreReg(Rn, &success);
8595 if (!success)
8596 return false;
8597
8598 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8599
8600 EmulateInstruction::Context context;
8601 context.type = EmulateInstruction::eContextImmediate;
8602 context.SetNoArgs ();
8603
8604 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8605 return false;
8606
8607 return true;
8608}
8609
8610// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8611// result to the destination register. It can optionally update the condition flags based on the result.
8612bool
8613EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8614{
8615#if 0
8616 // ARM pseudo code...
8617 if ConditionPassed() then
8618 EncodingSpecificOperations();
8619 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8620 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8621 if d == 15 then // Can only occur for ARM encoding
8622 ALUWritePC(result); // setflags is always FALSE here
8623 else
8624 R[d] = result;
8625 if setflags then
8626 APSR.N = result<31>;
8627 APSR.Z = IsZeroBit(result);
8628 APSR.C = carry;
8629 APSR.V = overflow;
8630#endif
8631
8632 bool success = false;
8633 const uint32_t opcode = OpcodeAsUnsigned (&success);
8634 if (!success)
8635 return false;
8636
8637 uint32_t Rd; // the destination register
8638 uint32_t Rn; // the first operand
8639 uint32_t Rm; // the second operand
8640 bool setflags;
8641 ARM_ShifterType shift_t;
8642 uint32_t shift_n; // the shift applied to the value read from Rm
8643 switch (encoding) {
8644 case eEncodingT1:
8645 Rd = Bits32(opcode, 11, 8);
8646 Rn = Bits32(opcode, 19, 16);
8647 Rm = Bits32(opcode, 3, 0);
8648 setflags = BitIsSet(opcode, 20);
8649 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8650 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8651 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8652 return false;
8653 break;
8654 case eEncodingA1:
8655 Rd = Bits32(opcode, 15, 12);
8656 Rn = Bits32(opcode, 19, 16);
8657 Rm = Bits32(opcode, 3, 0);
8658 setflags = BitIsSet(opcode, 20);
8659 shift_n = DecodeImmShiftARM(opcode, shift_t);
8660 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8661 // TODO: Emulate SUBS PC, LR and related instructions.
8662 if (Rd == 15 && setflags)
8663 return false;
8664 break;
8665 default:
8666 return false;
8667 }
8668 // Read the register value from register Rn.
8669 uint32_t val1 = ReadCoreReg(Rn, &success);
8670 if (!success)
8671 return false;
8672
8673 // Read the register value from register Rm.
8674 uint32_t val2 = ReadCoreReg(Rm, &success);
8675 if (!success)
8676 return false;
8677
8678 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8679 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8680
8681 EmulateInstruction::Context context;
8682 context.type = EmulateInstruction::eContextImmediate;
8683 context.SetNoArgs();
8684 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8685 return false;
8686
8687 return true;
8688}
8689
Johnny Chen90e607b2011-02-23 00:07:09 +00008690// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8691// an immediate value, and writes the result to the destination register. It can optionally update the condition
8692// flags based on the result.
8693bool
8694EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8695{
8696#if 0
8697 // ARM pseudo code...
8698 if ConditionPassed() then
8699 EncodingSpecificOperations();
8700 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8701 if d == 15 then
8702 ALUWritePC(result); // setflags is always FALSE here
8703 else
8704 R[d] = result;
8705 if setflags then
8706 APSR.N = result<31>;
8707 APSR.Z = IsZeroBit(result);
8708 APSR.C = carry;
8709 APSR.V = overflow;
8710#endif
8711
8712 bool success = false;
8713 const uint32_t opcode = OpcodeAsUnsigned (&success);
8714 if (!success)
8715 return false;
8716
8717 uint32_t Rd; // the destination register
8718 uint32_t Rn; // the first operand
8719 bool setflags;
8720 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8721 switch (encoding) {
8722 case eEncodingA1:
8723 Rd = Bits32(opcode, 15, 12);
8724 Rn = Bits32(opcode, 19, 16);
8725 setflags = BitIsSet(opcode, 20);
8726 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8727 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8728 // TODO: Emulate SUBS PC, LR and related instructions.
8729 if (Rd == 15 && setflags)
8730 return false;
8731 break;
8732 default:
8733 return false;
8734 }
8735 // Read the register value from the operand register Rn.
8736 uint32_t reg_val = ReadCoreReg(Rn, &success);
8737 if (!success)
8738 return false;
8739
8740 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8741
8742 EmulateInstruction::Context context;
8743 context.type = EmulateInstruction::eContextImmediate;
8744 context.SetNoArgs ();
8745
8746 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8747 return false;
8748
8749 return true;
8750}
8751
8752// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8753// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8754// condition flags based on the result.
8755bool
8756EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8757{
8758#if 0
8759 // ARM pseudo code...
8760 if ConditionPassed() then
8761 EncodingSpecificOperations();
8762 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8763 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8764 if d == 15 then
8765 ALUWritePC(result); // setflags is always FALSE here
8766 else
8767 R[d] = result;
8768 if setflags then
8769 APSR.N = result<31>;
8770 APSR.Z = IsZeroBit(result);
8771 APSR.C = carry;
8772 APSR.V = overflow;
8773#endif
8774
8775 bool success = false;
8776 const uint32_t opcode = OpcodeAsUnsigned (&success);
8777 if (!success)
8778 return false;
8779
8780 uint32_t Rd; // the destination register
8781 uint32_t Rn; // the first operand
8782 uint32_t Rm; // the second operand
8783 bool setflags;
8784 ARM_ShifterType shift_t;
8785 uint32_t shift_n; // the shift applied to the value read from Rm
8786 switch (encoding) {
8787 case eEncodingA1:
8788 Rd = Bits32(opcode, 15, 12);
8789 Rn = Bits32(opcode, 19, 16);
8790 Rm = Bits32(opcode, 3, 0);
8791 setflags = BitIsSet(opcode, 20);
8792 shift_n = DecodeImmShiftARM(opcode, shift_t);
8793 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8794 // TODO: Emulate SUBS PC, LR and related instructions.
8795 if (Rd == 15 && setflags)
8796 return false;
8797 break;
8798 default:
8799 return false;
8800 }
8801 // Read the register value from register Rn.
8802 uint32_t val1 = ReadCoreReg(Rn, &success);
8803 if (!success)
8804 return false;
8805
8806 // Read the register value from register Rm.
8807 uint32_t val2 = ReadCoreReg(Rm, &success);
8808 if (!success)
8809 return false;
8810
8811 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8812 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8813
8814 EmulateInstruction::Context context;
8815 context.type = EmulateInstruction::eContextImmediate;
8816 context.SetNoArgs();
8817 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8818 return false;
8819
8820 return true;
8821}
8822
Johnny Chen9b381772011-02-23 01:01:21 +00008823// Subtract with Carry (immediate) subtracts an immediate value and the value of
8824// NOT (Carry flag) from a register value, and writes the result to the destination register.
8825// It can optionally update the condition flags based on the result.
8826bool
8827EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8828{
8829#if 0
8830 // ARM pseudo code...
8831 if ConditionPassed() then
8832 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008833 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008834 if d == 15 then // Can only occur for ARM encoding
8835 ALUWritePC(result); // setflags is always FALSE here
8836 else
8837 R[d] = result;
8838 if setflags then
8839 APSR.N = result<31>;
8840 APSR.Z = IsZeroBit(result);
8841 APSR.C = carry;
8842 APSR.V = overflow;
8843#endif
8844
8845 bool success = false;
8846 const uint32_t opcode = OpcodeAsUnsigned (&success);
8847 if (!success)
8848 return false;
8849
8850 uint32_t Rd; // the destination register
8851 uint32_t Rn; // the first operand
8852 bool setflags;
8853 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8854 switch (encoding) {
8855 case eEncodingT1:
8856 Rd = Bits32(opcode, 11, 8);
8857 Rn = Bits32(opcode, 19, 16);
8858 setflags = BitIsSet(opcode, 20);
8859 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8860 if (BadReg(Rd) || BadReg(Rn))
8861 return false;
8862 break;
8863 case eEncodingA1:
8864 Rd = Bits32(opcode, 15, 12);
8865 Rn = Bits32(opcode, 19, 16);
8866 setflags = BitIsSet(opcode, 20);
8867 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8868 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8869 // TODO: Emulate SUBS PC, LR and related instructions.
8870 if (Rd == 15 && setflags)
8871 return false;
8872 break;
8873 default:
8874 return false;
8875 }
8876 // Read the register value from the operand register Rn.
8877 uint32_t reg_val = ReadCoreReg(Rn, &success);
8878 if (!success)
8879 return false;
8880
8881 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8882
8883 EmulateInstruction::Context context;
8884 context.type = EmulateInstruction::eContextImmediate;
8885 context.SetNoArgs ();
8886
8887 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8888 return false;
8889
8890 return true;
8891}
8892
8893// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8894// NOT (Carry flag) from a register value, and writes the result to the destination register.
8895// It can optionally update the condition flags based on the result.
8896bool
8897EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8898{
8899#if 0
8900 // ARM pseudo code...
8901 if ConditionPassed() then
8902 EncodingSpecificOperations();
8903 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8904 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8905 if d == 15 then // Can only occur for ARM encoding
8906 ALUWritePC(result); // setflags is always FALSE here
8907 else
8908 R[d] = result;
8909 if setflags then
8910 APSR.N = result<31>;
8911 APSR.Z = IsZeroBit(result);
8912 APSR.C = carry;
8913 APSR.V = overflow;
8914#endif
8915
8916 bool success = false;
8917 const uint32_t opcode = OpcodeAsUnsigned (&success);
8918 if (!success)
8919 return false;
8920
8921 uint32_t Rd; // the destination register
8922 uint32_t Rn; // the first operand
8923 uint32_t Rm; // the second operand
8924 bool setflags;
8925 ARM_ShifterType shift_t;
8926 uint32_t shift_n; // the shift applied to the value read from Rm
8927 switch (encoding) {
8928 case eEncodingT1:
8929 Rd = Rn = Bits32(opcode, 2, 0);
8930 Rm = Bits32(opcode, 5, 3);
8931 setflags = !InITBlock();
8932 shift_t = SRType_LSL;
8933 shift_n = 0;
8934 break;
8935 case eEncodingT2:
8936 Rd = Bits32(opcode, 11, 8);
8937 Rn = Bits32(opcode, 19, 16);
8938 Rm = Bits32(opcode, 3, 0);
8939 setflags = BitIsSet(opcode, 20);
8940 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8941 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8942 return false;
8943 break;
8944 case eEncodingA1:
8945 Rd = Bits32(opcode, 15, 12);
8946 Rn = Bits32(opcode, 19, 16);
8947 Rm = Bits32(opcode, 3, 0);
8948 setflags = BitIsSet(opcode, 20);
8949 shift_n = DecodeImmShiftARM(opcode, shift_t);
8950 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8951 // TODO: Emulate SUBS PC, LR and related instructions.
8952 if (Rd == 15 && setflags)
8953 return false;
8954 break;
8955 default:
8956 return false;
8957 }
8958 // Read the register value from register Rn.
8959 uint32_t val1 = ReadCoreReg(Rn, &success);
8960 if (!success)
8961 return false;
8962
8963 // Read the register value from register Rm.
8964 uint32_t val2 = ReadCoreReg(Rm, &success);
8965 if (!success)
8966 return false;
8967
8968 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8969 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8970
8971 EmulateInstruction::Context context;
8972 context.type = EmulateInstruction::eContextImmediate;
8973 context.SetNoArgs();
8974 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8975 return false;
8976
8977 return true;
8978}
8979
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008980// This instruction subtracts an immediate value from a register value, and writes the result
8981// to the destination register. It can optionally update the condition flags based on the result.
8982bool
8983EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8984{
8985#if 0
8986 // ARM pseudo code...
8987 if ConditionPassed() then
8988 EncodingSpecificOperations();
8989 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8990 R[d] = result;
8991 if setflags then
8992 APSR.N = result<31>;
8993 APSR.Z = IsZeroBit(result);
8994 APSR.C = carry;
8995 APSR.V = overflow;
8996#endif
8997
8998 bool success = false;
8999 const uint32_t opcode = OpcodeAsUnsigned (&success);
9000 if (!success)
9001 return false;
9002
9003 uint32_t Rd; // the destination register
9004 uint32_t Rn; // the first operand
9005 bool setflags;
9006 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9007 switch (encoding) {
9008 case eEncodingT1:
9009 Rd = Bits32(opcode, 2, 0);
9010 Rn = Bits32(opcode, 5, 3);
9011 setflags = !InITBlock();
9012 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9013 break;
9014 case eEncodingT2:
9015 Rd = Rn = Bits32(opcode, 10, 8);
9016 setflags = !InITBlock();
9017 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9018 break;
9019 case eEncodingT3:
9020 Rd = Bits32(opcode, 11, 8);
9021 Rn = Bits32(opcode, 19, 16);
9022 setflags = BitIsSet(opcode, 20);
9023 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9024
9025 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9026 if (Rd == 15 && setflags)
9027 return EmulateCMPImm(eEncodingT2);
9028
9029 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9030 if (Rn == 13)
9031 return EmulateSUBSPImm(eEncodingT2);
9032
9033 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9034 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9035 return false;
9036 break;
9037 case eEncodingT4:
9038 Rd = Bits32(opcode, 11, 8);
9039 Rn = Bits32(opcode, 19, 16);
9040 setflags = BitIsSet(opcode, 20);
9041 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9042
9043 // if Rn == '1111' then SEE ADR;
9044 if (Rn == 15)
9045 return EmulateADR(eEncodingT2);
9046
9047 // if Rn == '1101' then SEE SUB (SP minus immediate);
9048 if (Rn == 13)
9049 return EmulateSUBSPImm(eEncodingT3);
9050
9051 if (BadReg(Rd))
9052 return false;
9053 break;
9054 default:
9055 return false;
9056 }
9057 // Read the register value from the operand register Rn.
9058 uint32_t reg_val = ReadCoreReg(Rn, &success);
9059 if (!success)
9060 return false;
9061
9062 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9063
9064 EmulateInstruction::Context context;
9065 context.type = EmulateInstruction::eContextImmediate;
9066 context.SetNoArgs ();
9067
9068 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9069 return false;
9070
9071 return true;
9072}
9073
9074// This instruction subtracts an immediate value from a register value, and writes the result
9075// to the destination register. It can optionally update the condition flags based on the result.
9076bool
9077EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
9078{
9079#if 0
9080 // ARM pseudo code...
9081 if ConditionPassed() then
9082 EncodingSpecificOperations();
9083 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9084 if d == 15 then
9085 ALUWritePC(result); // setflags is always FALSE here
9086 else
9087 R[d] = result;
9088 if setflags then
9089 APSR.N = result<31>;
9090 APSR.Z = IsZeroBit(result);
9091 APSR.C = carry;
9092 APSR.V = overflow;
9093#endif
9094
9095 bool success = false;
9096 const uint32_t opcode = OpcodeAsUnsigned (&success);
9097 if (!success)
9098 return false;
9099
9100 uint32_t Rd; // the destination register
9101 uint32_t Rn; // the first operand
9102 bool setflags;
9103 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9104 switch (encoding) {
9105 case eEncodingA1:
9106 Rd = Bits32(opcode, 15, 12);
9107 Rn = Bits32(opcode, 19, 16);
9108 setflags = BitIsSet(opcode, 20);
9109 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9110
9111 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
9112 if (Rn == 15 && !setflags)
9113 return EmulateADR(eEncodingA2);
9114
9115 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9116 if (Rn == 13)
9117 return EmulateSUBSPImm(eEncodingA1);
9118
9119 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9120 // TODO: Emulate SUBS PC, LR and related instructions.
9121 if (Rd == 15 && setflags)
9122 return false;
9123 break;
9124 default:
9125 return false;
9126 }
9127 // Read the register value from the operand register Rn.
9128 uint32_t reg_val = ReadCoreReg(Rn, &success);
9129 if (!success)
9130 return false;
9131
9132 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9133
9134 EmulateInstruction::Context context;
9135 context.type = EmulateInstruction::eContextImmediate;
9136 context.SetNoArgs ();
9137
9138 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9139 return false;
9140
9141 return true;
9142}
9143
Johnny Chen2115b412011-02-21 23:42:44 +00009144// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9145// immediate value. It updates the condition flags based on the result, and discards the result.
9146bool
9147EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
9148{
9149#if 0
9150 // ARM pseudo code...
9151 if ConditionPassed() then
9152 EncodingSpecificOperations();
9153 result = R[n] EOR imm32;
9154 APSR.N = result<31>;
9155 APSR.Z = IsZeroBit(result);
9156 APSR.C = carry;
9157 // APSR.V unchanged
9158#endif
9159
9160 bool success = false;
9161 const uint32_t opcode = OpcodeAsUnsigned (&success);
9162 if (!success)
9163 return false;
9164
9165 if (ConditionPassed())
9166 {
9167 uint32_t Rn;
9168 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9169 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9170 switch (encoding)
9171 {
9172 case eEncodingT1:
9173 Rn = Bits32(opcode, 19, 16);
9174 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9175 if (BadReg(Rn))
9176 return false;
9177 break;
9178 case eEncodingA1:
9179 Rn = Bits32(opcode, 19, 16);
9180 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9181 break;
9182 default:
9183 return false;
9184 }
9185
9186 // Read the first operand.
9187 uint32_t val1 = ReadCoreReg(Rn, &success);
9188 if (!success)
9189 return false;
9190
9191 uint32_t result = val1 ^ imm32;
9192
9193 EmulateInstruction::Context context;
9194 context.type = EmulateInstruction::eContextImmediate;
9195 context.SetNoArgs ();
9196
9197 if (!WriteFlags(context, result, carry))
9198 return false;
9199 }
9200 return true;
9201}
9202
9203// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9204// optionally-shifted register value. It updates the condition flags based on the result, and discards
9205// the result.
9206bool
9207EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
9208{
9209#if 0
9210 // ARM pseudo code...
9211 if ConditionPassed() then
9212 EncodingSpecificOperations();
9213 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9214 result = R[n] EOR shifted;
9215 APSR.N = result<31>;
9216 APSR.Z = IsZeroBit(result);
9217 APSR.C = carry;
9218 // APSR.V unchanged
9219#endif
9220
9221 bool success = false;
9222 const uint32_t opcode = OpcodeAsUnsigned (&success);
9223 if (!success)
9224 return false;
9225
9226 if (ConditionPassed())
9227 {
9228 uint32_t Rn, Rm;
9229 ARM_ShifterType shift_t;
9230 uint32_t shift_n; // the shift applied to the value read from Rm
9231 uint32_t carry;
9232 switch (encoding)
9233 {
9234 case eEncodingT1:
9235 Rn = Bits32(opcode, 19, 16);
9236 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009237 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009238 if (BadReg(Rn) || BadReg(Rm))
9239 return false;
9240 break;
9241 case eEncodingA1:
9242 Rn = Bits32(opcode, 19, 16);
9243 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009244 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009245 break;
9246 default:
9247 return false;
9248 }
9249
9250 // Read the first operand.
9251 uint32_t val1 = ReadCoreReg(Rn, &success);
9252 if (!success)
9253 return false;
9254
9255 // Read the second operand.
9256 uint32_t val2 = ReadCoreReg(Rm, &success);
9257 if (!success)
9258 return false;
9259
9260 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9261 uint32_t result = val1 ^ shifted;
9262
9263 EmulateInstruction::Context context;
9264 context.type = EmulateInstruction::eContextImmediate;
9265 context.SetNoArgs ();
9266
9267 if (!WriteFlags(context, result, carry))
9268 return false;
9269 }
9270 return true;
9271}
9272
Johnny Chende3cce32011-02-21 21:24:49 +00009273// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9274// It updates the condition flags based on the result, and discards the result.
9275bool
9276EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
9277{
9278#if 0
9279 // ARM pseudo code...
9280 if ConditionPassed() then
9281 EncodingSpecificOperations();
9282 result = R[n] AND imm32;
9283 APSR.N = result<31>;
9284 APSR.Z = IsZeroBit(result);
9285 APSR.C = carry;
9286 // APSR.V unchanged
9287#endif
9288
9289 bool success = false;
9290 const uint32_t opcode = OpcodeAsUnsigned (&success);
9291 if (!success)
9292 return false;
9293
9294 if (ConditionPassed())
9295 {
9296 uint32_t Rn;
9297 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9298 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9299 switch (encoding)
9300 {
9301 case eEncodingT1:
9302 Rn = Bits32(opcode, 19, 16);
9303 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9304 if (BadReg(Rn))
9305 return false;
9306 break;
9307 case eEncodingA1:
9308 Rn = Bits32(opcode, 19, 16);
9309 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9310 break;
9311 default:
9312 return false;
9313 }
9314
9315 // Read the first operand.
9316 uint32_t val1 = ReadCoreReg(Rn, &success);
9317 if (!success)
9318 return false;
9319
9320 uint32_t result = val1 & imm32;
9321
9322 EmulateInstruction::Context context;
9323 context.type = EmulateInstruction::eContextImmediate;
9324 context.SetNoArgs ();
9325
9326 if (!WriteFlags(context, result, carry))
9327 return false;
9328 }
9329 return true;
9330}
9331
9332// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9333// It updates the condition flags based on the result, and discards the result.
9334bool
9335EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9336{
9337#if 0
9338 // ARM pseudo code...
9339 if ConditionPassed() then
9340 EncodingSpecificOperations();
9341 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9342 result = R[n] AND shifted;
9343 APSR.N = result<31>;
9344 APSR.Z = IsZeroBit(result);
9345 APSR.C = carry;
9346 // APSR.V unchanged
9347#endif
9348
9349 bool success = false;
9350 const uint32_t opcode = OpcodeAsUnsigned (&success);
9351 if (!success)
9352 return false;
9353
9354 if (ConditionPassed())
9355 {
9356 uint32_t Rn, Rm;
9357 ARM_ShifterType shift_t;
9358 uint32_t shift_n; // the shift applied to the value read from Rm
9359 uint32_t carry;
9360 switch (encoding)
9361 {
9362 case eEncodingT1:
9363 Rn = Bits32(opcode, 2, 0);
9364 Rm = Bits32(opcode, 5, 3);
9365 shift_t = SRType_LSL;
9366 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009367 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009368 case eEncodingT2:
9369 Rn = Bits32(opcode, 19, 16);
9370 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009371 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009372 if (BadReg(Rn) || BadReg(Rm))
9373 return false;
9374 break;
9375 case eEncodingA1:
9376 Rn = Bits32(opcode, 19, 16);
9377 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009378 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009379 break;
9380 default:
9381 return false;
9382 }
9383
9384 // Read the first operand.
9385 uint32_t val1 = ReadCoreReg(Rn, &success);
9386 if (!success)
9387 return false;
9388
9389 // Read the second operand.
9390 uint32_t val2 = ReadCoreReg(Rm, &success);
9391 if (!success)
9392 return false;
9393
9394 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9395 uint32_t result = val1 & shifted;
9396
9397 EmulateInstruction::Context context;
9398 context.type = EmulateInstruction::eContextImmediate;
9399 context.SetNoArgs ();
9400
9401 if (!WriteFlags(context, result, carry))
9402 return false;
9403 }
9404 return true;
9405}
9406
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009407EmulateInstructionARM::ARMOpcode*
9408EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009409{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009410 static ARMOpcode
9411 g_arm_opcodes[] =
9412 {
9413 //----------------------------------------------------------------------
9414 // Prologue instructions
9415 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009416
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009417 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009418 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9419 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009420
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009421 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009422 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009423 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009424 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009425 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9426 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009427 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009428
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009429 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009430 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009431
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009432 // push one register
9433 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009434 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009435
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009436 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009437 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9438 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009439
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009440 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009441 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009442 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009443
Johnny Chen9f687722011-02-18 00:02:28 +00009444 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9445 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009446 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009447 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9448
9449 //----------------------------------------------------------------------
9450 // Supervisor Call (previously Software Interrupt)
9451 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009452 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9453
9454 //----------------------------------------------------------------------
9455 // Branch instructions
9456 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009457 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009458 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9459 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9460 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9461 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009462 // for example, "bx lr"
9463 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009464 // bxj
9465 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009466
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009467 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009468 // Data-processing instructions
9469 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009470 // adc (immediate)
9471 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9472 // adc (register)
9473 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009474 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009475 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009476 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009477 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009478 // adr
9479 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9480 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009481 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009482 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009483 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009484 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009485 // bic (immediate)
9486 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9487 // bic (register)
9488 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009489 // eor (immediate)
9490 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9491 // eor (register)
9492 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009493 // orr (immediate)
9494 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9495 // orr (register)
9496 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009497 // rsb (immediate)
9498 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9499 // rsb (register)
9500 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009501 // rsc (immediate)
9502 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9503 // rsc (register)
9504 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009505 // sbc (immediate)
9506 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9507 // sbc (register)
9508 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009509 // sub (immediate, ARM)
9510 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009511 // sub (sp minus immediate)
9512 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009513 // teq (immediate)
9514 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9515 // teq (register)
9516 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009517 // tst (immediate)
9518 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9519 // tst (register)
9520 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9521
9522
Johnny Chen01d61572011-02-25 00:23:25 +00009523 // mov (register)
9524 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009525 // mvn (immediate)
9526 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9527 // mvn (register)
9528 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009529 // cmn (immediate)
9530 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9531 // cmn (register)
9532 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009533 // cmp (immediate)
9534 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9535 // cmp (register)
9536 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009537 // asr (immediate)
9538 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009539 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009540 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009541 // lsl (immediate)
9542 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9543 // lsl (register)
9544 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9545 // lsr (immediate)
9546 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9547 // lsr (register)
9548 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009549 // rrx is a special case encoding of ror (immediate)
9550 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9551 // ror (immediate)
9552 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9553 // ror (register)
9554 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009555 // mul
9556 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009557
9558 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009559 // Load instructions
9560 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009561 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009562 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009563 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009564 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009565 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009566 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009567 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009568 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009569 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009570 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009571 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009572 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009573 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009574 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009575 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9576 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009577
9578 //----------------------------------------------------------------------
9579 // Store instructions
9580 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009581 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009582 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009583 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009584 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009585 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009586 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009587
Caroline Tice6bf65162011-03-03 17:42:58 +00009588 //----------------------------------------------------------------------
9589 // Other instructions
9590 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009591 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009592 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009593 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009594 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9595 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009596
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009597 };
9598 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9599
9600 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9601 {
9602 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9603 return &g_arm_opcodes[i];
9604 }
9605 return NULL;
9606}
Greg Clayton64c84432011-01-21 22:02:52 +00009607
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009608
9609EmulateInstructionARM::ARMOpcode*
9610EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009611{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009612
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009613 static ARMOpcode
9614 g_thumb_opcodes[] =
9615 {
9616 //----------------------------------------------------------------------
9617 // Prologue instructions
9618 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009619
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009620 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009621 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9622 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9623 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009624
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009625 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009626 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009627 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009628 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009629 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009630 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009631
Johnny Chen864a8e82011-02-18 00:07:39 +00009632 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009633 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009634
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009635 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009636 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009637 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009638 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9639 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009640
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009641 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009642 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9643 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009644
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009645 //----------------------------------------------------------------------
9646 // Epilogue instructions
9647 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009648
Caroline Ticee2212882011-03-22 22:38:28 +00009649 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009650 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009651 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9652 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9653 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009654 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9655 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009656
9657 //----------------------------------------------------------------------
9658 // Supervisor Call (previously Software Interrupt)
9659 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009660 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9661
9662 //----------------------------------------------------------------------
9663 // If Then makes up to four following instructions conditional.
9664 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009665 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9666
9667 //----------------------------------------------------------------------
9668 // Branch instructions
9669 //----------------------------------------------------------------------
9670 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9671 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +00009672 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009673 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009674 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009675 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009676 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009677 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009678 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009679 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009680 // for example, "bx lr"
9681 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009682 // bxj
9683 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009684 // compare and branch
9685 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009686 // table branch byte
9687 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9688 // table branch halfword
9689 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009690
9691 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009692 // Data-processing instructions
9693 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009694 // adc (immediate)
9695 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9696 // adc (register)
9697 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9698 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9699 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009700 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009701 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009702 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009703 // adr
9704 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9705 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9706 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009707 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009708 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009709 // and (register)
9710 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9711 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009712 // bic (immediate)
9713 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9714 // bic (register)
9715 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9716 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009717 // eor (immediate)
9718 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9719 // eor (register)
9720 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9721 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009722 // orr (immediate)
9723 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9724 // orr (register)
9725 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9726 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009727 // rsb (immediate)
9728 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9729 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9730 // rsb (register)
9731 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009732 // sbc (immediate)
9733 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9734 // sbc (register)
9735 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9736 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009737 // add (immediate, Thumb)
9738 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9739 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9740 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9741 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009742 // sub (immediate, Thumb)
9743 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9744 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9745 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9746 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009747 // sub (sp minus immediate)
9748 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9749 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009750 // teq (immediate)
9751 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9752 // teq (register)
9753 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009754 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009755 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009756 // tst (register)
9757 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9758 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9759
Johnny Chen7c5234d2011-02-18 23:41:11 +00009760
Johnny Chen338bf542011-02-10 19:29:03 +00009761 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009762 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009763 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009764 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009765 // mov{s}<c>.w <Rd>, <Rm>
9766 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009767 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009768 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9769 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009770 // mvn (immediate)
9771 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9772 // mvn (register)
9773 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9774 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009775 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009776 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009777 // cmn (register)
9778 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009779 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009780 // cmp (immediate)
9781 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009782 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009783 // cmp (register) (Rn and Rm both from r0-r7)
9784 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9785 // cmp (register) (Rn and Rm not both from r0-r7)
9786 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009787 // asr (immediate)
9788 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009789 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009790 // asr (register)
9791 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9792 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009793 // lsl (immediate)
9794 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9795 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9796 // lsl (register)
9797 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9798 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9799 // lsr (immediate)
9800 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9801 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9802 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009803 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009804 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009805 // rrx is a special case encoding of ror (immediate)
9806 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9807 // ror (immediate)
9808 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9809 // ror (register)
9810 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9811 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009812 // mul
9813 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9814 // mul
9815 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009816
Johnny Chen26863dc2011-02-09 23:43:29 +00009817 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009818 // Load instructions
9819 //----------------------------------------------------------------------
9820 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009821 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009822 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticebaf1f642011-03-24 19:23:45 +00009823 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9824 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
9825 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
9826 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
9827 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009828 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009829 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9830 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009831 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9832 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9833 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009834 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009835 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9836 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009837 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9838 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9839 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009840 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009841 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9842 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009843 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9844 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009845 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009846 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9847 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009848 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9849 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009850 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009851 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9852 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009853
9854 //----------------------------------------------------------------------
9855 // Store instructions
9856 //----------------------------------------------------------------------
9857 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009858 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009859 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009860 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9861 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9862 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9863 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9864 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9865 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9866 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9867 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009868 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009869 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9870 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009871
9872 //----------------------------------------------------------------------
9873 // Other instructions
9874 //----------------------------------------------------------------------
9875 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009876 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9877 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009878 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9879 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009880 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9881 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009882 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9883 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9884 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009885
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009886 };
9887
9888 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9889 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9890 {
9891 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9892 return &g_thumb_opcodes[i];
9893 }
9894 return NULL;
9895}
Greg Clayton64c84432011-01-21 22:02:52 +00009896
Greg Clayton31e2a382011-01-30 20:03:56 +00009897bool
Greg Clayton395fc332011-02-15 21:59:32 +00009898EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009899{
9900 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009901 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009902 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009903 {
Greg Clayton395fc332011-02-15 21:59:32 +00009904 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9905 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9906 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9907 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9908 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9909 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9910 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9911 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9912 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9913 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009914 }
9915 return m_arm_isa != 0;
9916}
9917
9918
Greg Clayton64c84432011-01-21 22:02:52 +00009919bool
9920EmulateInstructionARM::ReadInstruction ()
9921{
9922 bool success = false;
9923 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9924 if (success)
9925 {
9926 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9927 if (success)
9928 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009929 Context read_inst_context;
9930 read_inst_context.type = eContextReadOpcode;
9931 read_inst_context.SetNoArgs ();
9932
Greg Clayton64c84432011-01-21 22:02:52 +00009933 if (m_inst_cpsr & MASK_CPSR_T)
9934 {
9935 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009936 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009937
9938 if (success)
9939 {
9940 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9941 {
9942 m_inst.opcode_type = eOpcode16;
9943 m_inst.opcode.inst16 = thumb_opcode;
9944 }
9945 else
9946 {
9947 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009948 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009949 }
9950 }
9951 }
9952 else
9953 {
9954 m_inst_mode = eModeARM;
9955 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009956 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009957 }
9958 }
9959 }
9960 if (!success)
9961 {
9962 m_inst_mode = eModeInvalid;
9963 m_inst_pc = LLDB_INVALID_ADDRESS;
9964 }
9965 return success;
9966}
9967
Johnny Chenee9b1f72011-02-09 01:00:31 +00009968uint32_t
9969EmulateInstructionARM::ArchVersion ()
9970{
9971 return m_arm_isa;
9972}
9973
Greg Clayton64c84432011-01-21 22:02:52 +00009974bool
9975EmulateInstructionARM::ConditionPassed ()
9976{
9977 if (m_inst_cpsr == 0)
9978 return false;
9979
9980 const uint32_t cond = CurrentCond ();
9981
9982 if (cond == UINT32_MAX)
9983 return false;
9984
9985 bool result = false;
9986 switch (UnsignedBits(cond, 3, 1))
9987 {
9988 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9989 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9990 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9991 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9992 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9993 case 5:
9994 {
9995 bool n = (m_inst_cpsr & MASK_CPSR_N);
9996 bool v = (m_inst_cpsr & MASK_CPSR_V);
9997 result = n == v;
9998 }
9999 break;
10000 case 6:
10001 {
10002 bool n = (m_inst_cpsr & MASK_CPSR_N);
10003 bool v = (m_inst_cpsr & MASK_CPSR_V);
10004 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
10005 }
10006 break;
10007 case 7:
10008 result = true;
10009 break;
10010 }
10011
10012 if (cond & 1)
10013 result = !result;
10014 return result;
10015}
10016
Johnny Chen9ee056b2011-02-08 00:06:35 +000010017uint32_t
10018EmulateInstructionARM::CurrentCond ()
10019{
10020 switch (m_inst_mode)
10021 {
10022 default:
10023 case eModeInvalid:
10024 break;
10025
10026 case eModeARM:
10027 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
10028
10029 case eModeThumb:
10030 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
10031 // 'cond' field of the encoding.
10032 if (m_inst.opcode_type == eOpcode16 &&
10033 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
10034 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
10035 {
10036 return Bits32(m_inst.opcode.inst16, 11, 7);
10037 }
10038 else if (m_inst.opcode_type == eOpcode32 &&
10039 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
10040 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
10041 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
10042 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
10043 {
10044 return Bits32(m_inst.opcode.inst32, 25, 22);
10045 }
10046
10047 return m_it_session.GetCond();
10048 }
10049 return UINT32_MAX; // Return invalid value
10050}
10051
Johnny Chen9ee056b2011-02-08 00:06:35 +000010052bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000010053EmulateInstructionARM::InITBlock()
10054{
10055 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
10056}
10057
10058bool
10059EmulateInstructionARM::LastInITBlock()
10060{
10061 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
10062}
10063
Caroline Ticeb27771d2011-03-03 22:37:46 +000010064bool
10065EmulateInstructionARM::BadMode (uint32_t mode)
10066{
10067
10068 switch (mode)
10069 {
10070 case 16: return false; // '10000'
10071 case 17: return false; // '10001'
10072 case 18: return false; // '10010'
10073 case 19: return false; // '10011'
10074 case 22: return false; // '10110'
10075 case 23: return false; // '10111'
10076 case 27: return false; // '11011'
10077 case 31: return false; // '11111'
10078 default: return true;
10079 }
10080 return true;
10081}
10082
10083bool
10084EmulateInstructionARM::CurrentModeIsPrivileged ()
10085{
10086 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
10087
10088 if (BadMode (mode))
10089 return false;
10090
10091 if (mode == 16)
10092 return false;
10093
10094 return true;
10095}
10096
10097void
10098EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
10099{
10100 bool privileged = CurrentModeIsPrivileged();
10101
10102 uint32_t tmp_cpsr = 0;
10103
10104 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
10105
10106 if (BitIsSet (bytemask, 3))
10107 {
10108 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10109 if (affect_execstate)
10110 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10111 }
10112
10113 if (BitIsSet (bytemask, 2))
10114 {
10115 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10116 }
10117
10118 if (BitIsSet (bytemask, 1))
10119 {
10120 if (affect_execstate)
10121 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10122 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10123 if (privileged)
10124 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10125 }
10126
10127 if (BitIsSet (bytemask, 0))
10128 {
10129 if (privileged)
10130 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10131 if (affect_execstate)
10132 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10133 if (privileged)
10134 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10135 }
10136
10137 m_inst_cpsr = tmp_cpsr;
10138}
10139
10140
Johnny Chen098ae2d2011-02-12 00:50:05 +000010141bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000010142EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
10143{
10144 addr_t target;
10145
Johnny Chenee9b1f72011-02-09 01:00:31 +000010146 // Check the current instruction set.
10147 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010148 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010149 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000010150 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010151
Johnny Chen9ee056b2011-02-08 00:06:35 +000010152 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010153 return false;
10154
10155 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010156}
10157
10158// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
10159bool
Johnny Chen668b4512011-02-15 21:08:58 +000010160EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010161{
10162 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000010163 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
10164 // we want to record it and issue a WriteRegister callback so the clients
10165 // can track the mode changes accordingly.
10166 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010167
10168 if (BitIsSet(addr, 0))
10169 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010170 if (CurrentInstrSet() != eModeThumb)
10171 {
10172 SelectInstrSet(eModeThumb);
10173 cpsr_changed = true;
10174 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010175 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000010176 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010177 }
10178 else if (BitIsClear(addr, 1))
10179 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010180 if (CurrentInstrSet() != eModeARM)
10181 {
10182 SelectInstrSet(eModeARM);
10183 cpsr_changed = true;
10184 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010185 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000010186 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010187 }
10188 else
10189 return false; // address<1:0> == '10' => UNPREDICTABLE
10190
Johnny Chen0f309db2011-02-09 19:11:32 +000010191 if (cpsr_changed)
10192 {
Johnny Chen558133b2011-02-09 23:59:17 +000010193 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000010194 return false;
10195 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010196 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010197 return false;
10198
10199 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010200}
Greg Clayton64c84432011-01-21 22:02:52 +000010201
Johnny Chenee9b1f72011-02-09 01:00:31 +000010202// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10203bool
Johnny Chen668b4512011-02-15 21:08:58 +000010204EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000010205{
10206 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000010207 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000010208 else
10209 return BranchWritePC((const Context)context, addr);
10210}
10211
Johnny Chen26863dc2011-02-09 23:43:29 +000010212// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
10213bool
Johnny Chen668b4512011-02-15 21:08:58 +000010214EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000010215{
10216 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000010217 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000010218 else
10219 return BranchWritePC((const Context)context, addr);
10220}
10221
Johnny Chenee9b1f72011-02-09 01:00:31 +000010222EmulateInstructionARM::Mode
10223EmulateInstructionARM::CurrentInstrSet ()
10224{
10225 return m_inst_mode;
10226}
10227
10228// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010229// ReadInstruction() is performed. This function has a side effect of updating
10230// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010231bool
10232EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10233{
Johnny Chen558133b2011-02-09 23:59:17 +000010234 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010235 switch (arm_or_thumb)
10236 {
10237 default:
10238 return false;
10239 eModeARM:
10240 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010241 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010242 break;
10243 eModeThumb:
10244 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010245 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010246 break;
10247 }
10248 return true;
10249}
10250
Johnny Chenef21b592011-02-10 01:52:38 +000010251// This function returns TRUE if the processor currently provides support for
10252// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10253// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10254bool
10255EmulateInstructionARM::UnalignedSupport()
10256{
10257 return (ArchVersion() >= ARMv7);
10258}
10259
Johnny Chenbf6ad172011-02-11 01:29:53 +000010260// The main addition and subtraction instructions can produce status information
10261// about both unsigned carry and signed overflow conditions. This status
10262// information can be used to synthesize multi-word additions and subtractions.
10263EmulateInstructionARM::AddWithCarryResult
10264EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10265{
10266 uint32_t result;
10267 uint8_t carry_out;
10268 uint8_t overflow;
10269
10270 uint64_t unsigned_sum = x + y + carry_in;
10271 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10272
10273 result = UnsignedBits(unsigned_sum, 31, 0);
10274 carry_out = (result == unsigned_sum ? 0 : 1);
10275 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10276
10277 AddWithCarryResult res = { result, carry_out, overflow };
10278 return res;
10279}
10280
Johnny Chen157b9592011-02-18 21:13:05 +000010281uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010282EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010283{
Johnny Chene39f22d2011-02-19 01:36:13 +000010284 uint32_t reg_kind, reg_num;
10285 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010286 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010287 case SP_REG:
10288 reg_kind = eRegisterKindGeneric;
10289 reg_num = LLDB_REGNUM_GENERIC_SP;
10290 break;
10291 case LR_REG:
10292 reg_kind = eRegisterKindGeneric;
10293 reg_num = LLDB_REGNUM_GENERIC_RA;
10294 break;
10295 case PC_REG:
10296 reg_kind = eRegisterKindGeneric;
10297 reg_num = LLDB_REGNUM_GENERIC_PC;
10298 break;
10299 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010300 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010301 {
10302 reg_kind = eRegisterKindDWARF;
10303 reg_num = dwarf_r0 + num;
10304 }
Johnny Chen157b9592011-02-18 21:13:05 +000010305 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010306 {
10307 assert(0 && "Invalid register number");
10308 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010309 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010310 }
10311 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010312 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010313
10314 // Read our register.
10315 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10316
10317 // When executing an ARM instruction , PC reads as the address of the current
10318 // instruction plus 8.
10319 // When executing a Thumb instruction , PC reads as the address of the current
10320 // instruction plus 4.
10321 if (num == 15)
10322 {
10323 if (CurrentInstrSet() == eModeARM)
10324 val += 8;
10325 else
10326 val += 4;
10327 }
Johnny Chen157b9592011-02-18 21:13:05 +000010328
10329 return val;
10330}
10331
Johnny Chenca67d1c2011-02-17 01:35:27 +000010332// Write the result to the ARM core register Rd, and optionally update the
10333// condition flags based on the result.
10334//
10335// This helper method tries to encapsulate the following pseudocode from the
10336// ARM Architecture Reference Manual:
10337//
10338// if d == 15 then // Can only occur for encoding A1
10339// ALUWritePC(result); // setflags is always FALSE here
10340// else
10341// R[d] = result;
10342// if setflags then
10343// APSR.N = result<31>;
10344// APSR.Z = IsZeroBit(result);
10345// APSR.C = carry;
10346// // APSR.V unchanged
10347//
10348// In the above case, the API client does not pass in the overflow arg, which
10349// defaults to ~0u.
10350bool
Johnny Chen10530c22011-02-17 22:37:12 +000010351EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10352 const uint32_t result,
10353 const uint32_t Rd,
10354 bool setflags,
10355 const uint32_t carry,
10356 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010357{
10358 if (Rd == 15)
10359 {
10360 if (!ALUWritePC (context, result))
10361 return false;
10362 }
10363 else
10364 {
Johnny Chena695f952011-02-23 21:24:25 +000010365 uint32_t reg_kind, reg_num;
10366 switch (Rd)
10367 {
10368 case SP_REG:
10369 reg_kind = eRegisterKindGeneric;
10370 reg_num = LLDB_REGNUM_GENERIC_SP;
10371 break;
10372 case LR_REG:
10373 reg_kind = eRegisterKindGeneric;
10374 reg_num = LLDB_REGNUM_GENERIC_RA;
10375 break;
10376 default:
10377 reg_kind = eRegisterKindDWARF;
10378 reg_num = dwarf_r0 + Rd;
10379 }
10380 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010381 return false;
10382 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010383 return WriteFlags (context, result, carry, overflow);
10384 }
10385 return true;
10386}
10387
10388// This helper method tries to encapsulate the following pseudocode from the
10389// ARM Architecture Reference Manual:
10390//
10391// APSR.N = result<31>;
10392// APSR.Z = IsZeroBit(result);
10393// APSR.C = carry;
10394// APSR.V = overflow
10395//
10396// Default arguments can be specified for carry and overflow parameters, which means
10397// not to update the respective flags.
10398bool
10399EmulateInstructionARM::WriteFlags (Context &context,
10400 const uint32_t result,
10401 const uint32_t carry,
10402 const uint32_t overflow)
10403{
10404 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010405 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10406 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010407 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010408 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010409 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010410 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010411 if (m_new_inst_cpsr != m_inst_cpsr)
10412 {
10413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10414 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010415 }
10416 return true;
10417}
10418
Greg Clayton64c84432011-01-21 22:02:52 +000010419bool
10420EmulateInstructionARM::EvaluateInstruction ()
10421{
Johnny Chenc315f862011-02-05 00:46:10 +000010422 // Advance the ITSTATE bits to their values for the next instruction.
10423 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10424 m_it_session.ITAdvance();
10425
Greg Clayton64c84432011-01-21 22:02:52 +000010426 return false;
10427}