blob: 08529d1ca0b7f7fcbca2489dace70db396396e15 [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.
Greg Claytonb3448432011-03-24 21:19:54 +000027#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_opcode_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)
Caroline Tice1697dd72011-03-30 17:11:45 +0000132#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000133#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000134#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000135#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000136
Caroline Tice4f605582011-03-31 00:02:51 +0000137#define No_VFP 0
138#define VFPv1 (1u << 1)
139#define VFPv2 (1u << 2)
140#define VFPv3 (1u << 3)
141#define AdvancedSIMD (1u << 4)
142
143#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
144#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
145#define VFPv2v3 (VFPv2 | VFPv3)
146
Johnny Chen0e00af22011-02-10 19:40:42 +0000147//----------------------------------------------------------------------
148//
149// EmulateInstructionARM implementation
150//
151//----------------------------------------------------------------------
152
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000153void
154EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000155{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000156}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000157
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000158void
159EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000160{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000161}
162
Caroline Ticefa172202011-02-11 22:49:54 +0000163// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
164bool
165EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
166{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000167 EmulateInstruction::Context context;
168 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
169 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000170
171 uint32_t random_data = rand ();
172 const uint32_t addr_byte_size = GetAddressByteSize();
173
Caroline Ticecc96eb52011-02-17 19:20:40 +0000174 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000175 return false;
176
177 return true;
178}
179
Caroline Tice713c2662011-02-11 17:59:55 +0000180// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
181bool
182EmulateInstructionARM::WriteBits32Unknown (int n)
183{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000184 EmulateInstruction::Context context;
185 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
186 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000187
Johnny Chen62ff6f52011-02-11 18:11:22 +0000188 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000189 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
190
191 if (!success)
192 return false;
193
194 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
195 return false;
196
197 return true;
198}
199
Johnny Chen08c25e82011-01-31 18:02:28 +0000200// Push Multiple Registers stores multiple registers to the stack, storing to
201// consecutive memory locations ending just below the address in SP, and updates
202// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000203bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000204EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000205{
206#if 0
207 // ARM pseudo code...
208 if (ConditionPassed())
209 {
210 EncodingSpecificOperations();
211 NullCheckIfThumbEE(13);
212 address = SP - 4*BitCount(registers);
213
214 for (i = 0 to 14)
215 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000216 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000217 {
218 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
219 MemA[address,4] = bits(32) UNKNOWN;
220 else
221 MemA[address,4] = R[i];
222 address = address + 4;
223 }
224 }
225
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000226 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000227 MemA[address,4] = PCStoreValue();
228
229 SP = SP - 4*BitCount(registers);
230 }
231#endif
232
233 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000234 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000235 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000236 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000237 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000238 if (!success)
239 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000240 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000241 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000242 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000243 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000244 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000245 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000246 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000247 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000248 // if BitCount(registers) < 1 then UNPREDICTABLE;
249 if (BitCount(registers) < 1)
250 return false;
251 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 case eEncodingT2:
253 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000254 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000255 // if BitCount(registers) < 2 then UNPREDICTABLE;
256 if (BitCount(registers) < 2)
257 return false;
258 break;
259 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000261 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000262 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000265 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000266 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000267 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000268 // Instead of return false, let's handle the following case as well,
269 // which amounts to pushing one reg onto the full descending stacks.
270 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000271 break;
272 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000273 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000274 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000275 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000276 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000277 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000278 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000279 default:
280 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000281 }
Johnny Chence1ca772011-01-25 01:13:00 +0000282 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000283 addr_t addr = sp - sp_offset;
284 uint32_t i;
285
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000286 EmulateInstruction::Context context;
287 context.type = EmulateInstruction::eContextPushRegisterOnStack;
288 Register dwarf_reg;
289 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000290 Register sp_reg;
291 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000292 for (i=0; i<15; ++i)
293 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000294 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000296 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000297 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000298 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000299 if (!success)
300 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000301 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000302 return false;
303 addr += addr_byte_size;
304 }
305 }
306
Johnny Chen7c1bf922011-02-08 23:49:37 +0000307 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000309 dwarf_reg.num = dwarf_pc;
310 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000311 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000312 if (!success)
313 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000314 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000315 return false;
316 }
317
318 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000319 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000320
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000321 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000322 return false;
323 }
324 return true;
325}
326
Johnny Chenef85e912011-01-31 23:07:40 +0000327// Pop Multiple Registers loads multiple registers from the stack, loading from
328// consecutive memory locations staring at the address in SP, and updates
329// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000330bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000331EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000332{
333#if 0
334 // ARM pseudo code...
335 if (ConditionPassed())
336 {
337 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
338 address = SP;
339 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000340 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000341 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000342 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000343 if UnalignedAllowed then
344 LoadWritePC(MemU[address,4]);
345 else
346 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000347 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
348 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000349 }
350#endif
351
352 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000353
Greg Clayton7bc39082011-03-24 23:53:38 +0000354 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000355 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000356 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000357 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000358 if (!success)
359 return false;
360 uint32_t registers = 0;
361 uint32_t Rt; // the destination register
362 switch (encoding) {
363 case eEncodingT1:
364 registers = Bits32(opcode, 7, 0);
365 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000366 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000367 registers |= (1u << 15);
368 // if BitCount(registers) < 1 then UNPREDICTABLE;
369 if (BitCount(registers) < 1)
370 return false;
371 break;
372 case eEncodingT2:
373 // Ignore bit 13.
374 registers = Bits32(opcode, 15, 0) & ~0x2000;
375 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000376 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000378 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
379 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
380 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000381 break;
382 case eEncodingT3:
383 Rt = Bits32(opcode, 15, 12);
384 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000385 if (Rt == 13)
386 return false;
387 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 registers = (1u << Rt);
390 break;
391 case eEncodingA1:
392 registers = Bits32(opcode, 15, 0);
393 // Instead of return false, let's handle the following case as well,
394 // which amounts to popping one reg from the full descending stacks.
395 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
396
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000397 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000398 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000399 return false;
400 break;
401 case eEncodingA2:
402 Rt = Bits32(opcode, 15, 12);
403 // if t == 13 then UNPREDICTABLE;
404 if (Rt == dwarf_sp)
405 return false;
406 registers = (1u << Rt);
407 break;
408 default:
409 return false;
410 }
411 addr_t sp_offset = addr_byte_size * BitCount (registers);
412 addr_t addr = sp;
413 uint32_t i, data;
414
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 EmulateInstruction::Context context;
416 context.type = EmulateInstruction::eContextPopRegisterOffStack;
417 Register dwarf_reg;
418 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000419 Register sp_reg;
420 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000421 for (i=0; i<15; ++i)
422 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000423 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000424 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000425 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000426 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000427 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000428 if (!success)
429 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000430 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000431 return false;
432 addr += addr_byte_size;
433 }
434 }
435
Johnny Chen7c1bf922011-02-08 23:49:37 +0000436 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000437 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000438 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000439 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000440 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000441 if (!success)
442 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000443 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000444 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000445 return false;
446 addr += addr_byte_size;
447 }
448
449 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000450 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000451
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000452 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000453 return false;
454 }
455 return true;
456}
457
Johnny Chen5b442b72011-01-27 19:34:30 +0000458// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000459// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000460bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000461EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000462{
463#if 0
464 // ARM pseudo code...
465 if (ConditionPassed())
466 {
467 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000468 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000469 if d == 15 then
470 ALUWritePC(result); // setflags is always FALSE here
471 else
472 R[d] = result;
473 if setflags then
474 APSR.N = result<31>;
475 APSR.Z = IsZeroBit(result);
476 APSR.C = carry;
477 APSR.V = overflow;
478 }
479#endif
480
481 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000482
Greg Clayton7bc39082011-03-24 23:53:38 +0000483 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000484 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000485 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000486 if (!success)
487 return false;
488 uint32_t Rd; // the destination register
489 uint32_t imm32;
490 switch (encoding) {
491 case eEncodingT1:
492 Rd = 7;
493 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
494 break;
495 case eEncodingA1:
496 Rd = Bits32(opcode, 15, 12);
497 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
498 break;
499 default:
500 return false;
501 }
502 addr_t sp_offset = imm32;
503 addr_t addr = sp + sp_offset; // a pointer to the stack area
504
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000505 EmulateInstruction::Context context;
506 context.type = EmulateInstruction::eContextRegisterPlusOffset;
507 Register sp_reg;
508 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
509 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000510
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000512 return false;
513 }
514 return true;
515}
516
Johnny Chen2ccad832011-01-28 19:57:25 +0000517// Set r7 or ip to the current stack pointer.
518// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000519bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000520EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000521{
522#if 0
523 // ARM pseudo code...
524 if (ConditionPassed())
525 {
526 EncodingSpecificOperations();
527 result = R[m];
528 if d == 15 then
529 ALUWritePC(result); // setflags is always FALSE here
530 else
531 R[d] = result;
532 if setflags then
533 APSR.N = result<31>;
534 APSR.Z = IsZeroBit(result);
535 // APSR.C unchanged
536 // APSR.V unchanged
537 }
538#endif
539
540 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000541
Greg Clayton7bc39082011-03-24 23:53:38 +0000542 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000543 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000544 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000545 if (!success)
546 return false;
547 uint32_t Rd; // the destination register
548 switch (encoding) {
549 case eEncodingT1:
550 Rd = 7;
551 break;
552 case eEncodingA1:
553 Rd = 12;
554 break;
555 default:
556 return false;
557 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000558
559 EmulateInstruction::Context context;
560 context.type = EmulateInstruction::eContextRegisterPlusOffset;
561 Register sp_reg;
562 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
563 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000564
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000566 return false;
567 }
568 return true;
569}
570
Johnny Chen1c13b622011-01-29 00:11:15 +0000571// Move from high register (r8-r15) to low register (r0-r7).
572// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000573bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000574EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000575{
Greg Clayton7bc39082011-03-24 23:53:38 +0000576 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000577}
578
579// Move from register to register.
580// MOV (register)
581bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000582EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000583{
Johnny Chen1c13b622011-01-29 00:11:15 +0000584#if 0
585 // ARM pseudo code...
586 if (ConditionPassed())
587 {
588 EncodingSpecificOperations();
589 result = R[m];
590 if d == 15 then
591 ALUWritePC(result); // setflags is always FALSE here
592 else
593 R[d] = result;
594 if setflags then
595 APSR.N = result<31>;
596 APSR.Z = IsZeroBit(result);
597 // APSR.C unchanged
598 // APSR.V unchanged
599 }
600#endif
601
602 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000603
Greg Clayton7bc39082011-03-24 23:53:38 +0000604 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000605 {
606 uint32_t Rm; // the source register
607 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000608 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000609 switch (encoding) {
610 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000611 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000612 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000613 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000614 if (Rd == 15 && InITBlock() && !LastInITBlock())
615 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000616 break;
617 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000618 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000620 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000621 if (InITBlock())
622 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000623 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000624 case eEncodingT3:
625 Rd = Bits32(opcode, 11, 8);
626 Rm = Bits32(opcode, 3, 0);
627 setflags = BitIsSet(opcode, 20);
628 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
629 if (setflags && (BadReg(Rd) || BadReg(Rm)))
630 return false;
631 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
632 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
633 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000634 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000635 case eEncodingA1:
636 Rd = Bits32(opcode, 15, 12);
637 Rm = Bits32(opcode, 3, 0);
638 setflags = BitIsSet(opcode, 20);
639 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
640 // TODO: Emulate SUBS PC, LR and related instructions.
641 if (Rd == 15 && setflags)
642 return false;
643 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000644 default:
645 return false;
646 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000647 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000648 if (!success)
649 return false;
650
651 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000652 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000653 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000654 Register dwarf_reg;
655 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000656 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000657
Johnny Chen10530c22011-02-17 22:37:12 +0000658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000659 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000660 }
661 return true;
662}
663
Johnny Chen357c30f2011-02-14 22:04:25 +0000664// Move (immediate) writes an immediate value to the destination register. It
665// can optionally update the condition flags based on the value.
666// MOV (immediate)
667bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000668EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000669{
670#if 0
671 // ARM pseudo code...
672 if (ConditionPassed())
673 {
674 EncodingSpecificOperations();
675 result = imm32;
676 if d == 15 then // Can only occur for ARM encoding
677 ALUWritePC(result); // setflags is always FALSE here
678 else
679 R[d] = result;
680 if setflags then
681 APSR.N = result<31>;
682 APSR.Z = IsZeroBit(result);
683 APSR.C = carry;
684 // APSR.V unchanged
685 }
686#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000687
Greg Clayton7bc39082011-03-24 23:53:38 +0000688 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000689 {
690 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000691 uint32_t imm32; // the immediate value to be written to Rd
692 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
693 bool setflags;
694 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000695 case eEncodingT1:
696 Rd = Bits32(opcode, 10, 8);
697 setflags = !InITBlock();
698 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
699 carry = APSR_C;
700
701 break;
702
703 case eEncodingT2:
704 Rd = Bits32(opcode, 11, 8);
705 setflags = BitIsSet(opcode, 20);
706 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
707 if (BadReg(Rd))
708 return false;
709
710 break;
711
712 case eEncodingT3:
713 {
714 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
715 Rd = Bits32 (opcode, 11, 8);
716 setflags = false;
717 uint32_t imm4 = Bits32 (opcode, 19, 16);
718 uint32_t imm3 = Bits32 (opcode, 14, 12);
719 uint32_t i = Bit32 (opcode, 26);
720 uint32_t imm8 = Bits32 (opcode, 7, 0);
721 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
722
723 // if BadReg(d) then UNPREDICTABLE;
724 if (BadReg (Rd))
725 return false;
726 }
727 break;
728
729 case eEncodingA1:
730 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
731 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
732 Rd = Bits32 (opcode, 15, 12);
733 setflags = BitIsSet (opcode, 20);
734 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
735
736 break;
737
738 case eEncodingA2:
739 {
740 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
741 Rd = Bits32 (opcode, 15, 12);
742 setflags = false;
743 uint32_t imm4 = Bits32 (opcode, 19, 16);
744 uint32_t imm12 = Bits32 (opcode, 11, 0);
745 imm32 = (imm4 << 12) | imm12;
746
747 // if d == 15 then UNPREDICTABLE;
748 if (Rd == 15)
749 return false;
750 }
751 break;
752
753 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000754 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000755 }
756 uint32_t result = imm32;
757
758 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000759 EmulateInstruction::Context context;
760 context.type = EmulateInstruction::eContextImmediate;
761 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000762
Johnny Chen10530c22011-02-17 22:37:12 +0000763 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000764 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000765 }
766 return true;
767}
768
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000769// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
770// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
771// unsigned values.
772//
773// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
774// limited to only a few forms of the instruction.
775bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000776EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000777{
778#if 0
779 if ConditionPassed() then
780 EncodingSpecificOperations();
781 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
782 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
783 result = operand1 * operand2;
784 R[d] = result<31:0>;
785 if setflags then
786 APSR.N = result<31>;
787 APSR.Z = IsZeroBit(result);
788 if ArchVersion() == 4 then
789 APSR.C = bit UNKNOWN;
790 // else APSR.C unchanged
791 // APSR.V always unchanged
792#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000793
Greg Clayton7bc39082011-03-24 23:53:38 +0000794 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000795 {
796 uint32_t d;
797 uint32_t n;
798 uint32_t m;
799 bool setflags;
800
801 // EncodingSpecificOperations();
802 switch (encoding)
803 {
804 case eEncodingT1:
805 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
806 d = Bits32 (opcode, 2, 0);
807 n = Bits32 (opcode, 5, 3);
808 m = Bits32 (opcode, 2, 0);
809 setflags = !InITBlock();
810
811 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
812 if ((ArchVersion() < ARMv6) && (d == n))
813 return false;
814
815 break;
816
817 case eEncodingT2:
818 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
819 d = Bits32 (opcode, 11, 8);
820 n = Bits32 (opcode, 19, 16);
821 m = Bits32 (opcode, 3, 0);
822 setflags = false;
823
824 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
825 if (BadReg (d) || BadReg (n) || BadReg (m))
826 return false;
827
828 break;
829
830 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000831 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000832 d = Bits32 (opcode, 19, 16);
833 n = Bits32 (opcode, 3, 0);
834 m = Bits32 (opcode, 11, 8);
835 setflags = BitIsSet (opcode, 20);
836
837 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
838 if ((d == 15) || (n == 15) || (m == 15))
839 return false;
840
841 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
842 if ((ArchVersion() < ARMv6) && (d == n))
843 return false;
844
845 break;
846
847 default:
848 return false;
849 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000850
851 bool success = false;
852
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000853 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
854 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
855 if (!success)
856 return false;
857
858 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
859 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
860 if (!success)
861 return false;
862
863 // result = operand1 * operand2;
864 uint64_t result = operand1 * operand2;
865
866 // R[d] = result<31:0>;
867 Register op1_reg;
868 Register op2_reg;
869 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
870 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
871
872 EmulateInstruction::Context context;
873 context.type = eContextMultiplication;
874 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
875
876 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
877 return false;
878
879 // if setflags then
880 if (setflags)
881 {
882 // APSR.N = result<31>;
883 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000884 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000885 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
886 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000887 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000888 {
889 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
890 return false;
891 }
892
893 // if ArchVersion() == 4 then
894 // APSR.C = bit UNKNOWN;
895 }
896 }
897 return true;
898}
899
Johnny Chend642a6a2011-02-22 01:01:03 +0000900// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
901// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000902bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000903EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000904{
905#if 0
906 // ARM pseudo code...
907 if (ConditionPassed())
908 {
909 EncodingSpecificOperations();
910 result = NOT(imm32);
911 if d == 15 then // Can only occur for ARM encoding
912 ALUWritePC(result); // setflags is always FALSE here
913 else
914 R[d] = result;
915 if setflags then
916 APSR.N = result<31>;
917 APSR.Z = IsZeroBit(result);
918 APSR.C = carry;
919 // APSR.V unchanged
920 }
921#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000922
Greg Clayton7bc39082011-03-24 23:53:38 +0000923 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000924 {
925 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000926 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
927 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000928 bool setflags;
929 switch (encoding) {
930 case eEncodingT1:
931 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000932 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000933 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000934 break;
935 case eEncodingA1:
936 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000937 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000938 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
939 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
940 // TODO: Emulate SUBS PC, LR and related instructions.
941 if (Rd == 15 && setflags)
942 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000943 break;
944 default:
945 return false;
946 }
947 uint32_t result = ~imm32;
948
949 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000950 EmulateInstruction::Context context;
951 context.type = EmulateInstruction::eContextImmediate;
952 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000953
Johnny Chen10530c22011-02-17 22:37:12 +0000954 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000955 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000956 }
957 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000958}
959
Johnny Chend642a6a2011-02-22 01:01:03 +0000960// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
961// It can optionally update the condition flags based on the result.
962bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000963EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +0000964{
965#if 0
966 // ARM pseudo code...
967 if (ConditionPassed())
968 {
969 EncodingSpecificOperations();
970 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
971 result = NOT(shifted);
972 if d == 15 then // Can only occur for ARM encoding
973 ALUWritePC(result); // setflags is always FALSE here
974 else
975 R[d] = result;
976 if setflags then
977 APSR.N = result<31>;
978 APSR.Z = IsZeroBit(result);
979 APSR.C = carry;
980 // APSR.V unchanged
981 }
982#endif
983
Greg Clayton7bc39082011-03-24 23:53:38 +0000984 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +0000985 {
986 uint32_t Rm; // the source register
987 uint32_t Rd; // the destination register
988 ARM_ShifterType shift_t;
989 uint32_t shift_n; // the shift applied to the value read from Rm
990 bool setflags;
991 uint32_t carry; // the carry bit after the shift operation
992 switch (encoding) {
993 case eEncodingT1:
994 Rd = Bits32(opcode, 2, 0);
995 Rm = Bits32(opcode, 5, 3);
996 setflags = !InITBlock();
997 shift_t = SRType_LSL;
998 shift_n = 0;
999 if (InITBlock())
1000 return false;
1001 break;
1002 case eEncodingT2:
1003 Rd = Bits32(opcode, 11, 8);
1004 Rm = Bits32(opcode, 3, 0);
1005 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001006 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001007 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001008 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001009 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001010 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001011 case eEncodingA1:
1012 Rd = Bits32(opcode, 15, 12);
1013 Rm = Bits32(opcode, 3, 0);
1014 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001015 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001016 break;
1017 default:
1018 return false;
1019 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001020 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001021 uint32_t value = ReadCoreReg(Rm, &success);
1022 if (!success)
1023 return false;
1024
1025 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1026 uint32_t result = ~shifted;
1027
1028 // The context specifies that an immediate is to be moved into Rd.
1029 EmulateInstruction::Context context;
1030 context.type = EmulateInstruction::eContextImmediate;
1031 context.SetNoArgs ();
1032
1033 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1034 return false;
1035 }
1036 return true;
1037}
1038
Johnny Chen788e0552011-01-27 22:52:23 +00001039// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1040// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001041bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001042EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001043{
1044#if 0
1045 // ARM pseudo code...
1046 if (ConditionPassed())
1047 {
1048 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1049 base = Align(PC,4);
1050 address = if add then (base + imm32) else (base - imm32);
1051 data = MemU[address,4];
1052 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001053 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1054 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001055 R[t] = data;
1056 else // Can only apply before ARMv7
1057 if CurrentInstrSet() == InstrSet_ARM then
1058 R[t] = ROR(data, 8*UInt(address<1:0>));
1059 else
1060 R[t] = bits(32) UNKNOWN;
1061 }
1062#endif
1063
Greg Clayton7bc39082011-03-24 23:53:38 +00001064 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001065 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001066 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001067 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001068 if (!success)
1069 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001070
1071 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001072 EmulateInstruction::Context context;
1073 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1074 Register pc_reg;
1075 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1076 context.SetRegisterPlusOffset (pc_reg, 0);
1077
Johnny Chenc9de9102011-02-11 19:12:30 +00001078 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001079 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001080 bool add; // +imm32 or -imm32?
1081 addr_t base; // the base address
1082 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001083 uint32_t data; // the literal data value from the PC relative load
1084 switch (encoding) {
1085 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001086 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001087 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001088 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001089 break;
1090 case eEncodingT2:
1091 Rt = Bits32(opcode, 15, 12);
1092 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1093 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001094 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001095 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001096 break;
1097 default:
1098 return false;
1099 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001100
Johnny Chene39f22d2011-02-19 01:36:13 +00001101 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001102 if (add)
1103 address = base + imm32;
1104 else
1105 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001106
1107 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001108 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001109 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001110 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001111
1112 if (Rt == 15)
1113 {
1114 if (Bits32(address, 1, 0) == 0)
1115 {
1116 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001117 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001118 return false;
1119 }
1120 else
1121 return false;
1122 }
1123 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1124 {
1125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1126 return false;
1127 }
1128 else // We don't handle ARM for now.
1129 return false;
1130
Johnny Chen788e0552011-01-27 22:52:23 +00001131 }
1132 return true;
1133}
1134
Johnny Chen5b442b72011-01-27 19:34:30 +00001135// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001136// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001137bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001138EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001139{
1140#if 0
1141 // ARM pseudo code...
1142 if (ConditionPassed())
1143 {
1144 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001145 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001146 if d == 15 then // Can only occur for ARM encoding
1147 ALUWritePC(result); // setflags is always FALSE here
1148 else
1149 R[d] = result;
1150 if setflags then
1151 APSR.N = result<31>;
1152 APSR.Z = IsZeroBit(result);
1153 APSR.C = carry;
1154 APSR.V = overflow;
1155 }
1156#endif
1157
1158 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001159
Greg Clayton7bc39082011-03-24 23:53:38 +00001160 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001161 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001162 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001163 if (!success)
1164 return false;
1165 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001166 uint32_t d;
1167 bool setflags;
1168 switch (encoding)
1169 {
1170 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001171 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001172 d = Bits32 (opcode, 10, 8);
1173 setflags = false;
1174 imm32 = (Bits32 (opcode, 7, 0) << 2);
1175
1176 break;
1177
1178 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001179 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001180 d = 13;
1181 setflags = false;
1182 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1183
1184 break;
1185
1186 default:
1187 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001188 }
1189 addr_t sp_offset = imm32;
1190 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1191
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001192 EmulateInstruction::Context context;
1193 context.type = EmulateInstruction::eContextAdjustStackPointer;
1194 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001195
Caroline Ticee2212882011-03-22 22:38:28 +00001196 if (d == 15)
1197 {
1198 if (!ALUWritePC (context, addr))
1199 return false;
1200 }
1201 else
1202 {
1203 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1204 return false;
1205 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001206 }
1207 return true;
1208}
1209
1210// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001211// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001212bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001213EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001214{
1215#if 0
1216 // ARM pseudo code...
1217 if (ConditionPassed())
1218 {
1219 EncodingSpecificOperations();
1220 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001221 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001222 if d == 15 then
1223 ALUWritePC(result); // setflags is always FALSE here
1224 else
1225 R[d] = result;
1226 if setflags then
1227 APSR.N = result<31>;
1228 APSR.Z = IsZeroBit(result);
1229 APSR.C = carry;
1230 APSR.V = overflow;
1231 }
1232#endif
1233
1234 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001235
Greg Clayton7bc39082011-03-24 23:53:38 +00001236 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001237 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001238 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001239 if (!success)
1240 return false;
1241 uint32_t Rm; // the second operand
1242 switch (encoding) {
1243 case eEncodingT2:
1244 Rm = Bits32(opcode, 6, 3);
1245 break;
1246 default:
1247 return false;
1248 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001249 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001250 if (!success)
1251 return false;
1252
1253 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1254
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001255 EmulateInstruction::Context context;
1256 context.type = EmulateInstruction::eContextAdjustStackPointer;
1257 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001258
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001259 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001260 return false;
1261 }
1262 return true;
1263}
1264
Johnny Chen9b8d7832011-02-02 01:13:56 +00001265// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1266// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1267// from Thumb to ARM.
1268// BLX (immediate)
1269bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001270EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001271{
1272#if 0
1273 // ARM pseudo code...
1274 if (ConditionPassed())
1275 {
1276 EncodingSpecificOperations();
1277 if CurrentInstrSet() == InstrSet_ARM then
1278 LR = PC - 4;
1279 else
1280 LR = PC<31:1> : '1';
1281 if targetInstrSet == InstrSet_ARM then
1282 targetAddress = Align(PC,4) + imm32;
1283 else
1284 targetAddress = PC + imm32;
1285 SelectInstrSet(targetInstrSet);
1286 BranchWritePC(targetAddress);
1287 }
1288#endif
1289
Greg Clayton7bc39082011-03-24 23:53:38 +00001290 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291
Greg Clayton7bc39082011-03-24 23:53:38 +00001292 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001293 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001294 EmulateInstruction::Context context;
1295 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001296 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001297 if (!success)
1298 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001299 addr_t lr; // next instruction address
1300 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001301 int32_t imm32; // PC-relative offset
1302 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001303 case eEncodingT1:
1304 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001305 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001306 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001307 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001308 uint32_t J1 = Bit32(opcode, 13);
1309 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001310 uint32_t imm11 = Bits32(opcode, 10, 0);
1311 uint32_t I1 = !(J1 ^ S);
1312 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001313 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001314 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001315 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001316 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001317 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001318 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001319 break;
1320 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001321 case eEncodingT2:
1322 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001323 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001324 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001325 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001326 uint32_t J1 = Bit32(opcode, 13);
1327 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001328 uint32_t imm10L = Bits32(opcode, 10, 1);
1329 uint32_t I1 = !(J1 ^ S);
1330 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001331 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001332 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001333 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001334 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001335 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001336 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001337 break;
1338 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001339 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001340 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001341 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001342 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001343 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001344 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001345 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001346 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001347 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001348 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001349 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001350 break;
1351 default:
1352 return false;
1353 }
1354 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1355 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001356 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001357 return false;
1358 }
1359 return true;
1360}
1361
1362// Branch with Link and Exchange (register) calls a subroutine at an address and
1363// instruction set specified by a register.
1364// BLX (register)
1365bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001366EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001367{
1368#if 0
1369 // ARM pseudo code...
1370 if (ConditionPassed())
1371 {
1372 EncodingSpecificOperations();
1373 target = R[m];
1374 if CurrentInstrSet() == InstrSet_ARM then
1375 next_instr_addr = PC - 4;
1376 LR = next_instr_addr;
1377 else
1378 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001379 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001380 BXWritePC(target);
1381 }
1382#endif
1383
1384 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001385
Greg Clayton7bc39082011-03-24 23:53:38 +00001386 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001387 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001388 EmulateInstruction::Context context;
1389 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001390 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001391 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001392 if (!success)
1393 return false;
1394 uint32_t Rm; // the register with the target address
1395 switch (encoding) {
1396 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001397 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001398 Rm = Bits32(opcode, 6, 3);
1399 // if m == 15 then UNPREDICTABLE;
1400 if (Rm == 15)
1401 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001402 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001403 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001404 break;
1405 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001406 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001407 Rm = Bits32(opcode, 3, 0);
1408 // if m == 15 then UNPREDICTABLE;
1409 if (Rm == 15)
1410 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001411 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001412 default:
1413 return false;
1414 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001415 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001416 if (!success)
1417 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001418 Register dwarf_reg;
1419 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1420 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001421 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1422 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001423 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001424 return false;
1425 }
1426 return true;
1427}
1428
Johnny Chenab3b3512011-02-12 00:10:51 +00001429// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001430bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001431EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001432{
1433#if 0
1434 // ARM pseudo code...
1435 if (ConditionPassed())
1436 {
1437 EncodingSpecificOperations();
1438 BXWritePC(R[m]);
1439 }
1440#endif
1441
Greg Clayton7bc39082011-03-24 23:53:38 +00001442 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001443 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001444 EmulateInstruction::Context context;
1445 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001446 uint32_t Rm; // the register with the target address
1447 switch (encoding) {
1448 case eEncodingT1:
1449 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001450 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001451 return false;
1452 break;
1453 case eEncodingA1:
1454 Rm = Bits32(opcode, 3, 0);
1455 break;
1456 default:
1457 return false;
1458 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001459 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001460 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001461 if (!success)
1462 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001463
1464 Register dwarf_reg;
1465 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001466 context.SetRegister (dwarf_reg);
1467 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001468 return false;
1469 }
1470 return true;
1471}
1472
Johnny Chen59e6ab72011-02-24 21:01:20 +00001473// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1474// address and instruction set specified by a register as though it were a BX instruction.
1475//
1476// TODO: Emulate Jazelle architecture?
1477// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1478bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001479EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001480{
1481#if 0
1482 // ARM pseudo code...
1483 if (ConditionPassed())
1484 {
1485 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001486 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001487 BXWritePC(R[m]);
1488 else
1489 if JazelleAcceptsExecution() then
1490 SwitchToJazelleExecution();
1491 else
1492 SUBARCHITECTURE_DEFINED handler call;
1493 }
1494#endif
1495
Greg Clayton7bc39082011-03-24 23:53:38 +00001496 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001497 {
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 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001517 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001518 addr_t target = ReadCoreReg (Rm, &success);
1519 if (!success)
1520 return false;
1521
1522 Register dwarf_reg;
1523 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1524 context.SetRegister (dwarf_reg);
1525 if (!BXWritePC(context, target))
1526 return false;
1527 }
1528 return true;
1529}
1530
Johnny Chen0d0148e2011-01-28 02:26:08 +00001531// Set r7 to point to some ip offset.
1532// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001533bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001534EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001535{
1536#if 0
1537 // ARM pseudo code...
1538 if (ConditionPassed())
1539 {
1540 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001541 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001542 if d == 15 then // Can only occur for ARM encoding
1543 ALUWritePC(result); // setflags is always FALSE here
1544 else
1545 R[d] = result;
1546 if setflags then
1547 APSR.N = result<31>;
1548 APSR.Z = IsZeroBit(result);
1549 APSR.C = carry;
1550 APSR.V = overflow;
1551 }
1552#endif
1553
Greg Clayton7bc39082011-03-24 23:53:38 +00001554 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001555 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001556 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001557 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001558 if (!success)
1559 return false;
1560 uint32_t imm32;
1561 switch (encoding) {
1562 case eEncodingA1:
1563 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1564 break;
1565 default:
1566 return false;
1567 }
1568 addr_t ip_offset = imm32;
1569 addr_t addr = ip - ip_offset; // the adjusted ip value
1570
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001571 EmulateInstruction::Context context;
1572 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1573 Register dwarf_reg;
1574 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1575 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001576
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001577 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001578 return false;
1579 }
1580 return true;
1581}
1582
1583// Set ip to point to some stack offset.
1584// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001585bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001586EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001587{
1588#if 0
1589 // ARM pseudo code...
1590 if (ConditionPassed())
1591 {
1592 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001593 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001594 if d == 15 then // Can only occur for ARM encoding
1595 ALUWritePC(result); // setflags is always FALSE here
1596 else
1597 R[d] = result;
1598 if setflags then
1599 APSR.N = result<31>;
1600 APSR.Z = IsZeroBit(result);
1601 APSR.C = carry;
1602 APSR.V = overflow;
1603 }
1604#endif
1605
Greg Clayton7bc39082011-03-24 23:53:38 +00001606 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001607 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001608 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001609 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001610 if (!success)
1611 return false;
1612 uint32_t imm32;
1613 switch (encoding) {
1614 case eEncodingA1:
1615 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1616 break;
1617 default:
1618 return false;
1619 }
1620 addr_t sp_offset = imm32;
1621 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1622
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001623 EmulateInstruction::Context context;
1624 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1625 Register dwarf_reg;
1626 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1627 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001628
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001629 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001630 return false;
1631 }
1632 return true;
1633}
1634
Johnny Chenc9e747f2011-02-23 01:55:07 +00001635// This instruction subtracts an immediate value from the SP value, and writes
1636// the result to the destination register.
1637//
1638// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001639bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001640EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001641{
1642#if 0
1643 // ARM pseudo code...
1644 if (ConditionPassed())
1645 {
1646 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001647 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001648 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001649 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001650 else
1651 R[d] = result;
1652 if setflags then
1653 APSR.N = result<31>;
1654 APSR.Z = IsZeroBit(result);
1655 APSR.C = carry;
1656 APSR.V = overflow;
1657 }
1658#endif
1659
1660 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001661 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001662 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001663 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001664 if (!success)
1665 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001666
1667 uint32_t Rd;
1668 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001669 uint32_t imm32;
1670 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001671 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001672 Rd = 13;
1673 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001674 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001675 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001676 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001677 Rd = Bits32(opcode, 11, 8);
1678 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001679 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001680 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001681 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001682 if (Rd == 15 && !setflags)
1683 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001684 break;
1685 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001686 Rd = Bits32(opcode, 11, 8);
1687 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001688 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001689 if (Rd == 15)
1690 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001691 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001692 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001693 Rd = Bits32(opcode, 15, 12);
1694 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001695 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001696 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1697 // TODO: Emulate SUBS PC, LR and related instructions.
1698 if (Rd == 15 && setflags)
1699 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001700 break;
1701 default:
1702 return false;
1703 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001704 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1705
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001706 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001707 if (Rd == 13)
1708 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001709 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1710 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001711 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001712 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001713 }
1714 else
1715 {
1716 context.type = EmulateInstruction::eContextImmediate;
1717 context.SetNoArgs ();
1718 }
1719
1720 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001721 return false;
1722 }
1723 return true;
1724}
1725
Johnny Chen08c25e82011-01-31 18:02:28 +00001726// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001727bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001728EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001729{
1730#if 0
1731 // ARM pseudo code...
1732 if (ConditionPassed())
1733 {
1734 EncodingSpecificOperations();
1735 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1736 address = if index then offset_addr else R[n];
1737 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1738 if wback then R[n] = offset_addr;
1739 }
1740#endif
1741
1742 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001743
Greg Clayton7bc39082011-03-24 23:53:38 +00001744 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001745 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001746 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001747 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001748 if (!success)
1749 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001750 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001751 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001752 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1753
1754 bool index;
1755 bool add;
1756 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001757 switch (encoding) {
1758 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001759 Rt = Bits32(opcode, 15, 12);
1760 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001761 Rn = Bits32 (opcode, 19, 16);
1762
1763 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1764 return false;
1765
1766 index = BitIsSet (opcode, 24);
1767 add = BitIsSet (opcode, 23);
1768 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1769
1770 if (wback && ((Rn == 15) || (Rn == Rt)))
1771 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001772 break;
1773 default:
1774 return false;
1775 }
Caroline Tice3e407972011-03-18 19:41:00 +00001776 addr_t offset_addr;
1777 if (add)
1778 offset_addr = sp + imm12;
1779 else
1780 offset_addr = sp - imm12;
1781
1782 addr_t addr;
1783 if (index)
1784 addr = offset_addr;
1785 else
1786 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001787
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001788 EmulateInstruction::Context context;
1789 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001790 Register sp_reg;
1791 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1792 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001793 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001794 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001795 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001796 if (!success)
1797 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001798 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001799 return false;
1800 }
1801 else
1802 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001803 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001804 if (!success)
1805 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001806 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001807 return false;
1808 }
1809
Caroline Tice3e407972011-03-18 19:41:00 +00001810
1811 if (wback)
1812 {
1813 context.type = EmulateInstruction::eContextAdjustStackPointer;
1814 context.SetImmediateSigned (addr - sp);
1815 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1816 return false;
1817 }
Johnny Chence1ca772011-01-25 01:13:00 +00001818 }
1819 return true;
1820}
1821
Johnny Chen08c25e82011-01-31 18:02:28 +00001822// Vector Push stores multiple extension registers to the stack.
1823// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001824bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001825EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001826{
1827#if 0
1828 // ARM pseudo code...
1829 if (ConditionPassed())
1830 {
1831 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1832 address = SP - imm32;
1833 SP = SP - imm32;
1834 if single_regs then
1835 for r = 0 to regs-1
1836 MemA[address,4] = S[d+r]; address = address+4;
1837 else
1838 for r = 0 to regs-1
1839 // Store as two word-aligned words in the correct order for current endianness.
1840 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1841 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1842 address = address+8;
1843 }
1844#endif
1845
1846 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001847
Greg Clayton7bc39082011-03-24 23:53:38 +00001848 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001849 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001850 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001851 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001852 if (!success)
1853 return false;
1854 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001855 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001856 uint32_t imm32; // stack offset
1857 uint32_t regs; // number of registers
1858 switch (encoding) {
1859 case eEncodingT1:
1860 case eEncodingA1:
1861 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001862 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001863 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1864 // If UInt(imm8) is odd, see "FSTMX".
1865 regs = Bits32(opcode, 7, 0) / 2;
1866 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1867 if (regs == 0 || regs > 16 || (d + regs) > 32)
1868 return false;
1869 break;
1870 case eEncodingT2:
1871 case eEncodingA2:
1872 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001873 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001874 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1875 regs = Bits32(opcode, 7, 0);
1876 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1877 if (regs == 0 || regs > 16 || (d + regs) > 32)
1878 return false;
1879 break;
1880 default:
1881 return false;
1882 }
1883 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1884 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1885 addr_t sp_offset = imm32;
1886 addr_t addr = sp - sp_offset;
1887 uint32_t i;
1888
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001889 EmulateInstruction::Context context;
1890 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1891 Register dwarf_reg;
1892 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001893 Register sp_reg;
1894 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1895 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001896 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001897 dwarf_reg.num = start_reg + d + i;
1898 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001899 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001900 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001901 if (!success)
1902 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001903 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001904 return false;
1905 addr += reg_byte_size;
1906 }
1907
1908 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001909 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001910
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001911 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001912 return false;
1913 }
1914 return true;
1915}
1916
Johnny Chen587a0a42011-02-01 18:35:28 +00001917// Vector Pop loads multiple extension registers from the stack.
1918// It also updates SP to point just above the loaded data.
1919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001920EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001921{
1922#if 0
1923 // ARM pseudo code...
1924 if (ConditionPassed())
1925 {
1926 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1927 address = SP;
1928 SP = SP + imm32;
1929 if single_regs then
1930 for r = 0 to regs-1
1931 S[d+r] = MemA[address,4]; address = address+4;
1932 else
1933 for r = 0 to regs-1
1934 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1935 // Combine the word-aligned words in the correct order for current endianness.
1936 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1937 }
1938#endif
1939
1940 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001941
Greg Clayton7bc39082011-03-24 23:53:38 +00001942 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001943 {
1944 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001945 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001946 if (!success)
1947 return false;
1948 bool single_regs;
1949 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1950 uint32_t imm32; // stack offset
1951 uint32_t regs; // number of registers
1952 switch (encoding) {
1953 case eEncodingT1:
1954 case eEncodingA1:
1955 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001956 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001957 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1958 // If UInt(imm8) is odd, see "FLDMX".
1959 regs = Bits32(opcode, 7, 0) / 2;
1960 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1961 if (regs == 0 || regs > 16 || (d + regs) > 32)
1962 return false;
1963 break;
1964 case eEncodingT2:
1965 case eEncodingA2:
1966 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001967 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001968 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1969 regs = Bits32(opcode, 7, 0);
1970 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1971 if (regs == 0 || regs > 16 || (d + regs) > 32)
1972 return false;
1973 break;
1974 default:
1975 return false;
1976 }
1977 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1978 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1979 addr_t sp_offset = imm32;
1980 addr_t addr = sp;
1981 uint32_t i;
1982 uint64_t data; // uint64_t to accomodate 64-bit registers.
1983
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001984 EmulateInstruction::Context context;
1985 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1986 Register dwarf_reg;
1987 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001988 Register sp_reg;
1989 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1990 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00001991 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001992 dwarf_reg.num = start_reg + d + i;
1993 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001994 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001995 if (!success)
1996 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001997 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001998 return false;
1999 addr += reg_byte_size;
2000 }
2001
2002 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002003 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002004
2005 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2006 return false;
2007 }
2008 return true;
2009}
2010
Johnny Chenb77be412011-02-04 00:40:18 +00002011// SVC (previously SWI)
2012bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002013EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002014{
2015#if 0
2016 // ARM pseudo code...
2017 if (ConditionPassed())
2018 {
2019 EncodingSpecificOperations();
2020 CallSupervisor();
2021 }
2022#endif
2023
2024 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002025
Greg Clayton7bc39082011-03-24 23:53:38 +00002026 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002027 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002028 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002029 addr_t lr; // next instruction address
2030 if (!success)
2031 return false;
2032 uint32_t imm32; // the immediate constant
2033 uint32_t mode; // ARM or Thumb mode
2034 switch (encoding) {
2035 case eEncodingT1:
2036 lr = (pc + 2) | 1u; // return address
2037 imm32 = Bits32(opcode, 7, 0);
2038 mode = eModeThumb;
2039 break;
2040 case eEncodingA1:
2041 lr = pc + 4; // return address
2042 imm32 = Bits32(opcode, 23, 0);
2043 mode = eModeARM;
2044 break;
2045 default:
2046 return false;
2047 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002048
2049 EmulateInstruction::Context context;
2050 context.type = EmulateInstruction::eContextSupervisorCall;
2051 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002052 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2053 return false;
2054 }
2055 return true;
2056}
2057
Johnny Chenc315f862011-02-05 00:46:10 +00002058// If Then makes up to four following instructions (the IT block) conditional.
2059bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002060EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002061{
2062#if 0
2063 // ARM pseudo code...
2064 EncodingSpecificOperations();
2065 ITSTATE.IT<7:0> = firstcond:mask;
2066#endif
2067
Johnny Chenc315f862011-02-05 00:46:10 +00002068 m_it_session.InitIT(Bits32(opcode, 7, 0));
2069 return true;
2070}
2071
Johnny Chen3b620b32011-02-07 20:11:47 +00002072// Branch causes a branch to a target address.
2073bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002074EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002075{
2076#if 0
2077 // ARM pseudo code...
2078 if (ConditionPassed())
2079 {
2080 EncodingSpecificOperations();
2081 BranchWritePC(PC + imm32);
2082 }
2083#endif
2084
2085 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002086
Greg Clayton7bc39082011-03-24 23:53:38 +00002087 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002088 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002089 EmulateInstruction::Context context;
2090 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002091 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002092 if (!success)
2093 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002094 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002095 int32_t imm32; // PC-relative offset
2096 switch (encoding) {
2097 case eEncodingT1:
2098 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2099 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002100 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002101 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002102 break;
2103 case eEncodingT2:
2104 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002105 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002106 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002107 break;
2108 case eEncodingT3:
2109 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2110 {
Johnny Chenbd599902011-02-10 21:39:01 +00002111 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002112 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002113 uint32_t J1 = Bit32(opcode, 13);
2114 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002115 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002116 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002117 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002118 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002119 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002120 break;
2121 }
2122 case eEncodingT4:
2123 {
Johnny Chenbd599902011-02-10 21:39:01 +00002124 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002125 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002126 uint32_t J1 = Bit32(opcode, 13);
2127 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002128 uint32_t imm11 = Bits32(opcode, 10, 0);
2129 uint32_t I1 = !(J1 ^ S);
2130 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002131 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002132 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002133 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002134 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002135 break;
2136 }
2137 case eEncodingA1:
2138 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002139 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002140 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002141 break;
2142 default:
2143 return false;
2144 }
2145 if (!BranchWritePC(context, target))
2146 return false;
2147 }
2148 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002149}
2150
Johnny Chen53ebab72011-02-08 23:21:57 +00002151// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2152// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2153// CBNZ, CBZ
2154bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002155EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002156{
2157#if 0
2158 // ARM pseudo code...
2159 EncodingSpecificOperations();
2160 if nonzero ^ IsZero(R[n]) then
2161 BranchWritePC(PC + imm32);
2162#endif
2163
2164 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002165
2166 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002167 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002168 if (!success)
2169 return false;
2170
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002171 EmulateInstruction::Context context;
2172 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002173 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002174 if (!success)
2175 return false;
2176
2177 addr_t target; // target address
2178 uint32_t imm32; // PC-relative offset to branch forward
2179 bool nonzero;
2180 switch (encoding) {
2181 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002182 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002183 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002184 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002185 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002186 break;
2187 default:
2188 return false;
2189 }
2190 if (nonzero ^ (reg_val == 0))
2191 if (!BranchWritePC(context, target))
2192 return false;
2193
2194 return true;
2195}
2196
Johnny Chen60299ec2011-02-17 19:34:27 +00002197// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2198// A base register provides a pointer to the table, and a second register supplies an index into the table.
2199// The branch length is twice the value of the byte returned from the table.
2200//
2201// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2202// A base register provides a pointer to the table, and a second register supplies an index into the table.
2203// The branch length is twice the value of the halfword returned from the table.
2204// TBB, TBH
2205bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002206EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002207{
2208#if 0
2209 // ARM pseudo code...
2210 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2211 if is_tbh then
2212 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2213 else
2214 halfwords = UInt(MemU[R[n]+R[m], 1]);
2215 BranchWritePC(PC + 2*halfwords);
2216#endif
2217
2218 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002219
2220 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2221 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2222 bool is_tbh; // true if table branch halfword
2223 switch (encoding) {
2224 case eEncodingT1:
2225 Rn = Bits32(opcode, 19, 16);
2226 Rm = Bits32(opcode, 3, 0);
2227 is_tbh = BitIsSet(opcode, 4);
2228 if (Rn == 13 || BadReg(Rm))
2229 return false;
2230 if (InITBlock() && !LastInITBlock())
2231 return false;
2232 break;
2233 default:
2234 return false;
2235 }
2236
2237 // Read the address of the table from the operand register Rn.
2238 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002239 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002240 if (!success)
2241 return false;
2242
2243 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002244 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002245 if (!success)
2246 return false;
2247
2248 // the offsetted table address
2249 addr_t addr = base + (is_tbh ? index*2 : index);
2250
2251 // PC-relative offset to branch forward
2252 EmulateInstruction::Context context;
2253 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002254 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002255 if (!success)
2256 return false;
2257
Johnny Chene39f22d2011-02-19 01:36:13 +00002258 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002259 if (!success)
2260 return false;
2261
2262 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002263 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002264 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2265 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2266
2267 if (!BranchWritePC(context, target))
2268 return false;
2269
2270 return true;
2271}
2272
Caroline Ticedcc11b32011-03-02 23:57:02 +00002273// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2274// It can optionally update the condition flags based on the result.
2275bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002276EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002277{
2278#if 0
2279 if ConditionPassed() then
2280 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002281 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002282 R[d] = result;
2283 if setflags then
2284 APSR.N = result<31>;
2285 APSR.Z = IsZeroBit(result);
2286 APSR.C = carry;
2287 APSR.V = overflow;
2288#endif
2289
2290 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002291
Greg Clayton7bc39082011-03-24 23:53:38 +00002292 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002293 {
2294 uint32_t d;
2295 uint32_t n;
2296 bool setflags;
2297 uint32_t imm32;
2298 uint32_t carry_out;
2299
2300 //EncodingSpecificOperations();
2301 switch (encoding)
2302 {
2303 case eEncodingT1:
2304 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2305 d = Bits32 (opcode, 2, 0);
2306 n = Bits32 (opcode, 5, 3);
2307 setflags = !InITBlock();
2308 imm32 = Bits32 (opcode, 8,6);
2309
2310 break;
2311
2312 case eEncodingT2:
2313 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2314 d = Bits32 (opcode, 10, 8);
2315 n = Bits32 (opcode, 10, 8);
2316 setflags = !InITBlock();
2317 imm32 = Bits32 (opcode, 7, 0);
2318
2319 break;
2320
2321 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002322 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2323 // if Rn == '1101' then SEE ADD (SP plus immediate);
2324 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002325 d = Bits32 (opcode, 11, 8);
2326 n = Bits32 (opcode, 19, 16);
2327 setflags = BitIsSet (opcode, 20);
2328 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2329
2330 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2331 if (BadReg (d) || (n == 15))
2332 return false;
2333
2334 break;
2335
2336 case eEncodingT4:
2337 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002338 // if Rn == '1111' then SEE ADR;
2339 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002340 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2341 d = Bits32 (opcode, 11, 8);
2342 n = Bits32 (opcode, 19, 16);
2343 setflags = false;
2344 uint32_t i = Bit32 (opcode, 26);
2345 uint32_t imm3 = Bits32 (opcode, 14, 12);
2346 uint32_t imm8 = Bits32 (opcode, 7, 0);
2347 imm32 = (i << 11) | (imm3 << 8) | imm8;
2348
2349 // if BadReg(d) then UNPREDICTABLE;
2350 if (BadReg (d))
2351 return false;
2352
2353 break;
2354 }
2355 default:
2356 return false;
2357 }
2358
2359 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2360 if (!success)
2361 return false;
2362
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002363 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002364 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2365
2366 Register reg_n;
2367 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2368
2369 EmulateInstruction::Context context;
2370 context.type = eContextAddition;
2371 context.SetRegisterPlusOffset (reg_n, imm32);
2372
2373 //R[d] = result;
2374 //if setflags then
2375 //APSR.N = result<31>;
2376 //APSR.Z = IsZeroBit(result);
2377 //APSR.C = carry;
2378 //APSR.V = overflow;
2379 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2380 return false;
2381
2382 }
2383 return true;
2384}
2385
Johnny Chen8fa20592011-02-18 01:22:22 +00002386// This instruction adds an immediate value to a register value, and writes the result to the destination
2387// register. It can optionally update the condition flags based on the result.
2388bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002389EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002390{
2391#if 0
2392 // ARM pseudo code...
2393 if ConditionPassed() then
2394 EncodingSpecificOperations();
2395 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2396 if d == 15 then
2397 ALUWritePC(result); // setflags is always FALSE here
2398 else
2399 R[d] = result;
2400 if setflags then
2401 APSR.N = result<31>;
2402 APSR.Z = IsZeroBit(result);
2403 APSR.C = carry;
2404 APSR.V = overflow;
2405#endif
2406
2407 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002408
Greg Clayton7bc39082011-03-24 23:53:38 +00002409 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002410 {
2411 uint32_t Rd, Rn;
2412 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2413 bool setflags;
2414 switch (encoding)
2415 {
2416 case eEncodingA1:
2417 Rd = Bits32(opcode, 15, 12);
2418 Rn = Bits32(opcode, 19, 16);
2419 setflags = BitIsSet(opcode, 20);
2420 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2421 break;
2422 default:
2423 return false;
2424 }
2425
Johnny Chen8fa20592011-02-18 01:22:22 +00002426 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002427 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002428 if (!success)
2429 return false;
2430
2431 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2432
2433 EmulateInstruction::Context context;
2434 context.type = EmulateInstruction::eContextImmediate;
2435 context.SetNoArgs ();
2436
2437 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2438 return false;
2439 }
2440 return true;
2441}
2442
Johnny Chend761dcf2011-02-17 22:03:29 +00002443// This instruction adds a register value and an optionally-shifted register value, and writes the result
2444// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002445bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002446EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002447{
2448#if 0
2449 // ARM pseudo code...
2450 if ConditionPassed() then
2451 EncodingSpecificOperations();
2452 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2453 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2454 if d == 15 then
2455 ALUWritePC(result); // setflags is always FALSE here
2456 else
2457 R[d] = result;
2458 if setflags then
2459 APSR.N = result<31>;
2460 APSR.Z = IsZeroBit(result);
2461 APSR.C = carry;
2462 APSR.V = overflow;
2463#endif
2464
2465 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002466
Greg Clayton7bc39082011-03-24 23:53:38 +00002467 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002468 {
2469 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002470 ARM_ShifterType shift_t;
2471 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002472 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002473 switch (encoding)
2474 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002475 case eEncodingT1:
2476 Rd = Bits32(opcode, 2, 0);
2477 Rn = Bits32(opcode, 5, 3);
2478 Rm = Bits32(opcode, 8, 6);
2479 setflags = !InITBlock();
2480 shift_t = SRType_LSL;
2481 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002482 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002483 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002484 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002485 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002486 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002487 shift_t = SRType_LSL;
2488 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002489 if (Rn == 15 && Rm == 15)
2490 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002491 if (Rd == 15 && InITBlock() && !LastInITBlock())
2492 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002493 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002494 case eEncodingA1:
2495 Rd = Bits32(opcode, 15, 12);
2496 Rn = Bits32(opcode, 19, 16);
2497 Rm = Bits32(opcode, 3, 0);
2498 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002499 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002500 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002501 default:
2502 return false;
2503 }
2504
Johnny Chen26863dc2011-02-09 23:43:29 +00002505 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002506 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002507 if (!success)
2508 return false;
2509
2510 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002511 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002512 if (!success)
2513 return false;
2514
Johnny Chene97c0d52011-02-18 19:32:20 +00002515 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002516 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002517
2518 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002519 context.type = EmulateInstruction::eContextAddition;
2520 Register op1_reg;
2521 Register op2_reg;
2522 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2523 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2524 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002525
Johnny Chen10530c22011-02-17 22:37:12 +00002526 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002527 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002528 }
2529 return true;
2530}
2531
Johnny Chen34075cb2011-02-22 01:56:31 +00002532// Compare Negative (immediate) adds a register value and an immediate value.
2533// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002534bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002535EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002536{
2537#if 0
2538 // ARM pseudo code...
2539 if ConditionPassed() then
2540 EncodingSpecificOperations();
2541 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2542 APSR.N = result<31>;
2543 APSR.Z = IsZeroBit(result);
2544 APSR.C = carry;
2545 APSR.V = overflow;
2546#endif
2547
2548 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002549
2550 uint32_t Rn; // the first operand
2551 uint32_t imm32; // the immediate value to be compared with
2552 switch (encoding) {
2553 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002554 Rn = Bits32(opcode, 19, 16);
2555 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2556 if (Rn == 15)
2557 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002558 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002559 case eEncodingA1:
2560 Rn = Bits32(opcode, 19, 16);
2561 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2562 break;
2563 default:
2564 return false;
2565 }
2566 // Read the register value from the operand register Rn.
2567 uint32_t reg_val = ReadCoreReg(Rn, &success);
2568 if (!success)
2569 return false;
2570
Johnny Chen078fbc62011-02-22 19:48:22 +00002571 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002572
2573 EmulateInstruction::Context context;
2574 context.type = EmulateInstruction::eContextImmediate;
2575 context.SetNoArgs ();
2576 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2577 return false;
2578
2579 return true;
2580}
2581
2582// Compare Negative (register) adds a register value and an optionally-shifted register value.
2583// It updates the condition flags based on the result, and discards the result.
2584bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002585EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002586{
2587#if 0
2588 // ARM pseudo code...
2589 if ConditionPassed() then
2590 EncodingSpecificOperations();
2591 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2592 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2593 APSR.N = result<31>;
2594 APSR.Z = IsZeroBit(result);
2595 APSR.C = carry;
2596 APSR.V = overflow;
2597#endif
2598
2599 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002600
2601 uint32_t Rn; // the first operand
2602 uint32_t Rm; // the second operand
2603 ARM_ShifterType shift_t;
2604 uint32_t shift_n; // the shift applied to the value read from Rm
2605 switch (encoding) {
2606 case eEncodingT1:
2607 Rn = Bits32(opcode, 2, 0);
2608 Rm = Bits32(opcode, 5, 3);
2609 shift_t = SRType_LSL;
2610 shift_n = 0;
2611 break;
2612 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002613 Rn = Bits32(opcode, 19, 16);
2614 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002615 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002616 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2617 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002618 return false;
2619 break;
2620 case eEncodingA1:
2621 Rn = Bits32(opcode, 19, 16);
2622 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002623 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002624 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002625 default:
2626 return false;
2627 }
2628 // Read the register value from register Rn.
2629 uint32_t val1 = ReadCoreReg(Rn, &success);
2630 if (!success)
2631 return false;
2632
2633 // Read the register value from register Rm.
2634 uint32_t val2 = ReadCoreReg(Rm, &success);
2635 if (!success)
2636 return false;
2637
2638 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002639 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002640
2641 EmulateInstruction::Context context;
2642 context.type = EmulateInstruction::eContextImmediate;
2643 context.SetNoArgs();
2644 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2645 return false;
2646
2647 return true;
2648}
2649
2650// Compare (immediate) subtracts an immediate value from a register value.
2651// It updates the condition flags based on the result, and discards the result.
2652bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002653EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002654{
2655#if 0
2656 // ARM pseudo code...
2657 if ConditionPassed() then
2658 EncodingSpecificOperations();
2659 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2660 APSR.N = result<31>;
2661 APSR.Z = IsZeroBit(result);
2662 APSR.C = carry;
2663 APSR.V = overflow;
2664#endif
2665
2666 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002667
2668 uint32_t Rn; // the first operand
2669 uint32_t imm32; // the immediate value to be compared with
2670 switch (encoding) {
2671 case eEncodingT1:
2672 Rn = Bits32(opcode, 10, 8);
2673 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002674 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002675 case eEncodingT2:
2676 Rn = Bits32(opcode, 19, 16);
2677 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2678 if (Rn == 15)
2679 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002680 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002681 case eEncodingA1:
2682 Rn = Bits32(opcode, 19, 16);
2683 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002684 break;
2685 default:
2686 return false;
2687 }
2688 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002689 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002690 if (!success)
2691 return false;
2692
Johnny Chen10530c22011-02-17 22:37:12 +00002693 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2694
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002695 EmulateInstruction::Context context;
2696 context.type = EmulateInstruction::eContextImmediate;
2697 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002698 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2699 return false;
2700
Johnny Chend4dc4442011-02-11 02:02:56 +00002701 return true;
2702}
2703
Johnny Chen34075cb2011-02-22 01:56:31 +00002704// Compare (register) subtracts an optionally-shifted register value from a register value.
2705// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002706bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002707EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002708{
2709#if 0
2710 // ARM pseudo code...
2711 if ConditionPassed() then
2712 EncodingSpecificOperations();
2713 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2714 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2715 APSR.N = result<31>;
2716 APSR.Z = IsZeroBit(result);
2717 APSR.C = carry;
2718 APSR.V = overflow;
2719#endif
2720
2721 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002722
2723 uint32_t Rn; // the first operand
2724 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002725 ARM_ShifterType shift_t;
2726 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002727 switch (encoding) {
2728 case eEncodingT1:
2729 Rn = Bits32(opcode, 2, 0);
2730 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002731 shift_t = SRType_LSL;
2732 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002733 break;
2734 case eEncodingT2:
2735 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2736 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002737 shift_t = SRType_LSL;
2738 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002739 if (Rn < 8 && Rm < 8)
2740 return false;
2741 if (Rn == 15 || Rm == 15)
2742 return false;
2743 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002744 case eEncodingA1:
2745 Rn = Bits32(opcode, 19, 16);
2746 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002747 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002748 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002749 default:
2750 return false;
2751 }
2752 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002753 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002754 if (!success)
2755 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002756
Johnny Chene4a4d302011-02-11 21:53:58 +00002757 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002758 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002759 if (!success)
2760 return false;
2761
Johnny Chen34075cb2011-02-22 01:56:31 +00002762 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2763 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002764
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002765 EmulateInstruction::Context context;
2766 context.type = EmulateInstruction::eContextImmediate;
2767 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002768 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2769 return false;
2770
Johnny Chene4a4d302011-02-11 21:53:58 +00002771 return true;
2772}
2773
Johnny Chen82f16aa2011-02-15 20:10:55 +00002774// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2775// shifting in copies of its sign bit, and writes the result to the destination register. It can
2776// optionally update the condition flags based on the result.
2777bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002778EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002779{
2780#if 0
2781 // ARM pseudo code...
2782 if ConditionPassed() then
2783 EncodingSpecificOperations();
2784 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2785 if d == 15 then // Can only occur for ARM encoding
2786 ALUWritePC(result); // setflags is always FALSE here
2787 else
2788 R[d] = result;
2789 if setflags then
2790 APSR.N = result<31>;
2791 APSR.Z = IsZeroBit(result);
2792 APSR.C = carry;
2793 // APSR.V unchanged
2794#endif
2795
Greg Clayton7bc39082011-03-24 23:53:38 +00002796 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002797}
2798
2799// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2800// shifting in copies of its sign bit, and writes the result to the destination register.
2801// The variable number of bits is read from the bottom byte of a register. It can optionally update
2802// the condition flags based on the result.
2803bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002804EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002805{
2806#if 0
2807 // ARM pseudo code...
2808 if ConditionPassed() then
2809 EncodingSpecificOperations();
2810 shift_n = UInt(R[m]<7:0>);
2811 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2812 R[d] = result;
2813 if setflags then
2814 APSR.N = result<31>;
2815 APSR.Z = IsZeroBit(result);
2816 APSR.C = carry;
2817 // APSR.V unchanged
2818#endif
2819
Greg Clayton7bc39082011-03-24 23:53:38 +00002820 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002821}
2822
2823// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2824// shifting in zeros, and writes the result to the destination register. It can optionally
2825// update the condition flags based on the result.
2826bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002827EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002828{
2829#if 0
2830 // ARM pseudo code...
2831 if ConditionPassed() then
2832 EncodingSpecificOperations();
2833 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2834 if d == 15 then // Can only occur for ARM encoding
2835 ALUWritePC(result); // setflags is always FALSE here
2836 else
2837 R[d] = result;
2838 if setflags then
2839 APSR.N = result<31>;
2840 APSR.Z = IsZeroBit(result);
2841 APSR.C = carry;
2842 // APSR.V unchanged
2843#endif
2844
Greg Clayton7bc39082011-03-24 23:53:38 +00002845 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002846}
2847
2848// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2849// shifting in zeros, and writes the result to the destination register. The variable number
2850// of bits is read from the bottom byte of a register. It can optionally update the condition
2851// flags based on the result.
2852bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002853EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002854{
2855#if 0
2856 // ARM pseudo code...
2857 if ConditionPassed() then
2858 EncodingSpecificOperations();
2859 shift_n = UInt(R[m]<7:0>);
2860 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2861 R[d] = result;
2862 if setflags then
2863 APSR.N = result<31>;
2864 APSR.Z = IsZeroBit(result);
2865 APSR.C = carry;
2866 // APSR.V unchanged
2867#endif
2868
Greg Clayton7bc39082011-03-24 23:53:38 +00002869 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002870}
2871
2872// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2873// shifting in zeros, and writes the result to the destination register. It can optionally
2874// update the condition flags based on the result.
2875bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002876EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002877{
2878#if 0
2879 // ARM pseudo code...
2880 if ConditionPassed() then
2881 EncodingSpecificOperations();
2882 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2883 if d == 15 then // Can only occur for ARM encoding
2884 ALUWritePC(result); // setflags is always FALSE here
2885 else
2886 R[d] = result;
2887 if setflags then
2888 APSR.N = result<31>;
2889 APSR.Z = IsZeroBit(result);
2890 APSR.C = carry;
2891 // APSR.V unchanged
2892#endif
2893
Greg Clayton7bc39082011-03-24 23:53:38 +00002894 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002895}
2896
2897// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2898// shifting in zeros, and writes the result to the destination register. The variable number
2899// of bits is read from the bottom byte of a register. It can optionally update the condition
2900// flags based on the result.
2901bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002902EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002903{
2904#if 0
2905 // ARM pseudo code...
2906 if ConditionPassed() then
2907 EncodingSpecificOperations();
2908 shift_n = UInt(R[m]<7:0>);
2909 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2910 R[d] = result;
2911 if setflags then
2912 APSR.N = result<31>;
2913 APSR.Z = IsZeroBit(result);
2914 APSR.C = carry;
2915 // APSR.V unchanged
2916#endif
2917
Greg Clayton7bc39082011-03-24 23:53:38 +00002918 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002919}
2920
Johnny Cheneeab4852011-02-16 22:14:44 +00002921// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2922// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2923// It can optionally update the condition flags based on the result.
2924bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002925EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002926{
2927#if 0
2928 // ARM pseudo code...
2929 if ConditionPassed() then
2930 EncodingSpecificOperations();
2931 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2932 if d == 15 then // Can only occur for ARM encoding
2933 ALUWritePC(result); // setflags is always FALSE here
2934 else
2935 R[d] = result;
2936 if setflags then
2937 APSR.N = result<31>;
2938 APSR.Z = IsZeroBit(result);
2939 APSR.C = carry;
2940 // APSR.V unchanged
2941#endif
2942
Greg Clayton7bc39082011-03-24 23:53:38 +00002943 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002944}
2945
2946// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2947// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2948// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2949// flags based on the result.
2950bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002951EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002952{
2953#if 0
2954 // ARM pseudo code...
2955 if ConditionPassed() then
2956 EncodingSpecificOperations();
2957 shift_n = UInt(R[m]<7:0>);
2958 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2959 R[d] = result;
2960 if setflags then
2961 APSR.N = result<31>;
2962 APSR.Z = IsZeroBit(result);
2963 APSR.C = carry;
2964 // APSR.V unchanged
2965#endif
2966
Greg Clayton7bc39082011-03-24 23:53:38 +00002967 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002968}
2969
2970// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2971// with the carry flag shifted into bit [31].
2972//
2973// RRX can optionally update the condition flags based on the result.
2974// In that case, bit [0] is shifted into the carry flag.
2975bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002976EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002977{
2978#if 0
2979 // ARM pseudo code...
2980 if ConditionPassed() then
2981 EncodingSpecificOperations();
2982 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2983 if d == 15 then // Can only occur for ARM encoding
2984 ALUWritePC(result); // setflags is always FALSE here
2985 else
2986 R[d] = result;
2987 if setflags then
2988 APSR.N = result<31>;
2989 APSR.Z = IsZeroBit(result);
2990 APSR.C = carry;
2991 // APSR.V unchanged
2992#endif
2993
Greg Clayton7bc39082011-03-24 23:53:38 +00002994 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00002995}
2996
Johnny Chen41a0a152011-02-16 01:27:54 +00002997bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002998EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00002999{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003000 assert(shift_type == SRType_ASR
3001 || shift_type == SRType_LSL
3002 || shift_type == SRType_LSR
3003 || shift_type == SRType_ROR
3004 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003005
Johnny Chen82f16aa2011-02-15 20:10:55 +00003006 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003007
Greg Clayton7bc39082011-03-24 23:53:38 +00003008 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003009 {
Johnny Chene7f89532011-02-15 23:22:46 +00003010 uint32_t Rd; // the destination register
3011 uint32_t Rm; // the first operand register
3012 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003013 uint32_t carry; // the carry bit after the shift operation
3014 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003015
3016 // Special case handling!
3017 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003018 ARMEncoding use_encoding = encoding;
3019 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003020 {
3021 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3022 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003023 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003024 }
3025
Greg Clayton7bc39082011-03-24 23:53:38 +00003026 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003027 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003028 // Due to the above special case handling!
3029 assert(shift_type != SRType_ROR);
3030
Johnny Chen82f16aa2011-02-15 20:10:55 +00003031 Rd = Bits32(opcode, 2, 0);
3032 Rm = Bits32(opcode, 5, 3);
3033 setflags = !InITBlock();
3034 imm5 = Bits32(opcode, 10, 6);
3035 break;
3036 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003037 // A8.6.141 RRX
3038 assert(shift_type != SRType_RRX);
3039
Johnny Chen82f16aa2011-02-15 20:10:55 +00003040 Rd = Bits32(opcode, 11, 8);
3041 Rm = Bits32(opcode, 3, 0);
3042 setflags = BitIsSet(opcode, 20);
3043 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3044 if (BadReg(Rd) || BadReg(Rm))
3045 return false;
3046 break;
3047 case eEncodingA1:
3048 Rd = Bits32(opcode, 15, 12);
3049 Rm = Bits32(opcode, 3, 0);
3050 setflags = BitIsSet(opcode, 20);
3051 imm5 = Bits32(opcode, 11, 7);
3052 break;
3053 default:
3054 return false;
3055 }
3056
Johnny Cheneeab4852011-02-16 22:14:44 +00003057 // A8.6.139 ROR (immediate)
3058 if (shift_type == SRType_ROR && imm5 == 0)
3059 shift_type = SRType_RRX;
3060
Johnny Chen82f16aa2011-02-15 20:10:55 +00003061 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003062 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003063 if (!success)
3064 return false;
3065
Johnny Cheneeab4852011-02-16 22:14:44 +00003066 // Decode the shift amount if not RRX.
3067 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003068
Johnny Chene97c0d52011-02-18 19:32:20 +00003069 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003070
3071 // The context specifies that an immediate is to be moved into Rd.
3072 EmulateInstruction::Context context;
3073 context.type = EmulateInstruction::eContextImmediate;
3074 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003075
Johnny Chen10530c22011-02-17 22:37:12 +00003076 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003077 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003078 }
3079 return true;
3080}
3081
Johnny Chene7f89532011-02-15 23:22:46 +00003082bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003083EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003084{
Johnny Chen41a0a152011-02-16 01:27:54 +00003085 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003086
3087 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003088
Greg Clayton7bc39082011-03-24 23:53:38 +00003089 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003090 {
3091 uint32_t Rd; // the destination register
3092 uint32_t Rn; // the first operand register
3093 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3094 uint32_t carry; // the carry bit after the shift operation
3095 bool setflags;
3096 switch (encoding) {
3097 case eEncodingT1:
3098 Rd = Bits32(opcode, 2, 0);
3099 Rn = Rd;
3100 Rm = Bits32(opcode, 5, 3);
3101 setflags = !InITBlock();
3102 break;
3103 case eEncodingT2:
3104 Rd = Bits32(opcode, 11, 8);
3105 Rn = Bits32(opcode, 19, 16);
3106 Rm = Bits32(opcode, 3, 0);
3107 setflags = BitIsSet(opcode, 20);
3108 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3109 return false;
3110 break;
3111 case eEncodingA1:
3112 Rd = Bits32(opcode, 15, 12);
3113 Rn = Bits32(opcode, 3, 0);
3114 Rm = Bits32(opcode, 11, 8);
3115 setflags = BitIsSet(opcode, 20);
3116 if (Rd == 15 || Rn == 15 || Rm == 15)
3117 return false;
3118 break;
3119 default:
3120 return false;
3121 }
3122
3123 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003124 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003125 if (!success)
3126 return false;
3127 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003128 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003129 if (!success)
3130 return false;
3131
3132 // Get the shift amount.
3133 uint32_t amt = Bits32(val, 7, 0);
3134
Johnny Chene97c0d52011-02-18 19:32:20 +00003135 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003136
3137 // The context specifies that an immediate is to be moved into Rd.
3138 EmulateInstruction::Context context;
3139 context.type = EmulateInstruction::eContextImmediate;
3140 context.SetNoArgs ();
3141
Johnny Chen10530c22011-02-17 22:37:12 +00003142 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003143 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003144 }
3145 return true;
3146}
3147
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003148// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003149// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003150// can be written back to the base register.
3151bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003152EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003153{
3154#if 0
3155 // ARM pseudo code...
3156 if ConditionPassed()
3157 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3158 address = R[n];
3159
3160 for i = 0 to 14
3161 if registers<i> == '1' then
3162 R[i] = MemA[address, 4]; address = address + 4;
3163 if registers<15> == '1' then
3164 LoadWritePC (MemA[address, 4]);
3165
3166 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3167 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3168
3169#endif
3170
3171 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003172
Greg Clayton7bc39082011-03-24 23:53:38 +00003173 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003174 {
3175 uint32_t n;
3176 uint32_t registers = 0;
3177 bool wback;
3178 const uint32_t addr_byte_size = GetAddressByteSize();
3179 switch (encoding)
3180 {
3181 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003182 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003183 n = Bits32 (opcode, 10, 8);
3184 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003185 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003186 wback = BitIsClear (registers, n);
3187 // if BitCount(registers) < 1 then UNPREDICTABLE;
3188 if (BitCount(registers) < 1)
3189 return false;
3190 break;
3191 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003192 // if W == '1' && Rn == '1101' then SEE POP;
3193 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003194 n = Bits32 (opcode, 19, 16);
3195 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003196 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003197 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003198
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003199 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003200 if ((n == 15)
3201 || (BitCount (registers) < 2)
3202 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3203 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003204
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003205 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003206 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003207 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003208
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003209 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003210 if (wback
3211 && BitIsSet (registers, n))
3212 return false;
3213 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003214
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003215 case eEncodingA1:
3216 n = Bits32 (opcode, 19, 16);
3217 registers = Bits32 (opcode, 15, 0);
3218 wback = BitIsSet (opcode, 21);
3219 if ((n == 15)
3220 || (BitCount (registers) < 1))
3221 return false;
3222 break;
3223 default:
3224 return false;
3225 }
3226
3227 int32_t offset = 0;
3228 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3229 if (!success)
3230 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003231
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003232 EmulateInstruction::Context context;
3233 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3234 Register dwarf_reg;
3235 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3236 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003237
3238 for (int i = 0; i < 14; ++i)
3239 {
3240 if (BitIsSet (registers, i))
3241 {
Caroline Tice85aab332011-02-08 23:56:10 +00003242 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003243 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244 if (wback && (n == 13)) // Pop Instruction
3245 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3246
3247 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003248 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003249 if (!success)
3250 return false;
3251
3252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3253 return false;
3254
3255 offset += addr_byte_size;
3256 }
3257 }
3258
3259 if (BitIsSet (registers, 15))
3260 {
3261 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003262 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003263 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003264 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003265 if (!success)
3266 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003267 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003268 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269 return false;
3270 }
3271
3272 if (wback && BitIsClear (registers, n))
3273 {
Caroline Ticefa172202011-02-11 22:49:54 +00003274 // R[n] = R[n] + 4 * BitCount (registers)
3275 int32_t offset = addr_byte_size * BitCount (registers);
3276 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003277 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003278
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3280 return false;
3281 }
3282 if (wback && BitIsSet (registers, n))
3283 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003284 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003285 }
3286 return true;
3287}
Caroline Tice713c2662011-02-11 17:59:55 +00003288
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003289// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3290// The consecutive memory locations end at this address and the address just below the lowest of those locations
3291// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003292bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003293EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003294{
3295#if 0
3296 // ARM pseudo code...
3297 if ConditionPassed() then
3298 EncodingSpecificOperations();
3299 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003300
Caroline Tice713c2662011-02-11 17:59:55 +00003301 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003302 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003303 R[i] = MemA[address,4]; address = address + 4;
3304
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003305 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003306 LoadWritePC(MemA[address,4]);
3307
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003308 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3309 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003310#endif
3311
3312 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003313
Greg Clayton7bc39082011-03-24 23:53:38 +00003314 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003315 {
3316 uint32_t n;
3317 uint32_t registers = 0;
3318 bool wback;
3319 const uint32_t addr_byte_size = GetAddressByteSize();
3320
3321 // EncodingSpecificOperations();
3322 switch (encoding)
3323 {
3324 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003325 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003326 n = Bits32 (opcode, 19, 16);
3327 registers = Bits32 (opcode, 15, 0);
3328 wback = BitIsSet (opcode, 21);
3329
3330 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3331 if ((n == 15) || (BitCount (registers) < 1))
3332 return false;
3333
3334 break;
3335
3336 default:
3337 return false;
3338 }
3339 // address = R[n] - 4*BitCount(registers) + 4;
3340
3341 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003342 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003343
3344 if (!success)
3345 return false;
3346
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003347 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003348
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003349 EmulateInstruction::Context context;
3350 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3351 Register dwarf_reg;
3352 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3353 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003354
3355 // for i = 0 to 14
3356 for (int i = 0; i < 14; ++i)
3357 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003358 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003359 if (BitIsSet (registers, i))
3360 {
3361 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003362 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003363 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003364 if (!success)
3365 return false;
3366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3367 return false;
3368 offset += addr_byte_size;
3369 }
3370 }
3371
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003372 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003373 // LoadWritePC(MemA[address,4]);
3374 if (BitIsSet (registers, 15))
3375 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003376 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003377 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003378 if (!success)
3379 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003380 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003381 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003382 return false;
3383 }
3384
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003385 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003386 if (wback && BitIsClear (registers, n))
3387 {
Caroline Tice713c2662011-02-11 17:59:55 +00003388 if (!success)
3389 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003390
3391 offset = (addr_byte_size * BitCount (registers)) * -1;
3392 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003393 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003394 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3396 return false;
3397 }
3398
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003399 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003400 if (wback && BitIsSet (registers, n))
3401 return WriteBits32Unknown (n);
3402 }
3403 return true;
3404}
3405
3406// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3407// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3408// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003409bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003410EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003411{
3412#if 0
3413 // ARM pseudo code...
3414 if ConditionPassed() then
3415 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3416 address = R[n] - 4*BitCount(registers);
3417
3418 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003419 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003420 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003421 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003422 LoadWritePC(MemA[address,4]);
3423
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003424 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3425 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003426#endif
3427
3428 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003429
Greg Clayton7bc39082011-03-24 23:53:38 +00003430 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003431 {
3432 uint32_t n;
3433 uint32_t registers = 0;
3434 bool wback;
3435 const uint32_t addr_byte_size = GetAddressByteSize();
3436 switch (encoding)
3437 {
3438 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003439 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003440 n = Bits32 (opcode, 19, 16);
3441 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003442 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003443 wback = BitIsSet (opcode, 21);
3444
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003445 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003446 if ((n == 15)
3447 || (BitCount (registers) < 2)
3448 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3449 return false;
3450
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003451 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003452 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003453 return false;
3454
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003455 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003456 if (wback && BitIsSet (registers, n))
3457 return false;
3458
3459 break;
3460
3461 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003462 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003463 n = Bits32 (opcode, 19, 16);
3464 registers = Bits32 (opcode, 15, 0);
3465 wback = BitIsSet (opcode, 21);
3466
3467 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3468 if ((n == 15) || (BitCount (registers) < 1))
3469 return false;
3470
3471 break;
3472
3473 default:
3474 return false;
3475 }
3476
Caroline Tice713c2662011-02-11 17:59:55 +00003477 // address = R[n] - 4*BitCount(registers);
3478
Caroline Tice0b29e242011-02-08 23:16:02 +00003479 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003480 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003481
3482 if (!success)
3483 return false;
3484
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003485 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003486 EmulateInstruction::Context context;
3487 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3488 Register dwarf_reg;
3489 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003490 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003491
3492 for (int i = 0; i < 14; ++i)
3493 {
3494 if (BitIsSet (registers, i))
3495 {
3496 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003497 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003498 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003499 if (!success)
3500 return false;
3501
3502 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3503 return false;
3504
3505 offset += addr_byte_size;
3506 }
3507 }
3508
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003509 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003510 // LoadWritePC(MemA[address,4]);
3511 if (BitIsSet (registers, 15))
3512 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003513 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003514 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003515 if (!success)
3516 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003517 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003518 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003519 return false;
3520 }
3521
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003522 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003523 if (wback && BitIsClear (registers, n))
3524 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003525 if (!success)
3526 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003527
3528 offset = (addr_byte_size * BitCount (registers)) * -1;
3529 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003530 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003531 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003532 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3533 return false;
3534 }
3535
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003536 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003537 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003538 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003539 }
3540 return true;
3541}
Caroline Tice85aab332011-02-08 23:56:10 +00003542
Caroline Tice713c2662011-02-11 17:59:55 +00003543// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3544// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3545// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003546bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003547EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003548{
3549#if 0
3550 if ConditionPassed() then
3551 EncodingSpecificOperations();
3552 address = R[n] + 4;
3553
3554 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003555 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003556 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003557 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003558 LoadWritePC(MemA[address,4]);
3559
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003560 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3561 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003562#endif
3563
3564 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003565
Greg Clayton7bc39082011-03-24 23:53:38 +00003566 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003567 {
3568 uint32_t n;
3569 uint32_t registers = 0;
3570 bool wback;
3571 const uint32_t addr_byte_size = GetAddressByteSize();
3572 switch (encoding)
3573 {
3574 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003575 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003576 n = Bits32 (opcode, 19, 16);
3577 registers = Bits32 (opcode, 15, 0);
3578 wback = BitIsSet (opcode, 21);
3579
3580 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3581 if ((n == 15) || (BitCount (registers) < 1))
3582 return false;
3583
3584 break;
3585 default:
3586 return false;
3587 }
3588 // address = R[n] + 4;
3589
3590 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003591 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003592
3593 if (!success)
3594 return false;
3595
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003596 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003597
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003598 EmulateInstruction::Context context;
3599 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3600 Register dwarf_reg;
3601 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3602 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003603
3604 for (int i = 0; i < 14; ++i)
3605 {
3606 if (BitIsSet (registers, i))
3607 {
3608 // R[i] = MemA[address,4]; address = address + 4;
3609
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003610 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003611 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003612 if (!success)
3613 return false;
3614
3615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3616 return false;
3617
3618 offset += addr_byte_size;
3619 }
3620 }
3621
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003622 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003623 // LoadWritePC(MemA[address,4]);
3624 if (BitIsSet (registers, 15))
3625 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003626 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003627 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003628 if (!success)
3629 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003630 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003631 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003632 return false;
3633 }
3634
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003635 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003636 if (wback && BitIsClear (registers, n))
3637 {
Caroline Tice85aab332011-02-08 23:56:10 +00003638 if (!success)
3639 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003640
3641 offset = addr_byte_size * BitCount (registers);
3642 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003643 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003644 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003645 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3646 return false;
3647 }
3648
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003649 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003650 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003651 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003652 }
3653 return true;
3654}
Caroline Tice0b29e242011-02-08 23:16:02 +00003655
Johnny Chenef21b592011-02-10 01:52:38 +00003656// Load Register (immediate) calculates an address from a base register value and
3657// an immediate offset, loads a word from memory, and writes to a register.
3658// LDR (immediate, Thumb)
3659bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003660EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003661{
3662#if 0
3663 // ARM pseudo code...
3664 if (ConditionPassed())
3665 {
3666 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3667 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3668 address = if index then offset_addr else R[n];
3669 data = MemU[address,4];
3670 if wback then R[n] = offset_addr;
3671 if t == 15 then
3672 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3673 elsif UnalignedSupport() || address<1:0> = '00' then
3674 R[t] = data;
3675 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3676 }
3677#endif
3678
3679 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003680
Greg Clayton7bc39082011-03-24 23:53:38 +00003681 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003682 {
3683 uint32_t Rt; // the destination register
3684 uint32_t Rn; // the base register
3685 uint32_t imm32; // the immediate offset used to form the address
3686 addr_t offset_addr; // the offset address
3687 addr_t address; // the calculated address
3688 uint32_t data; // the literal data value from memory load
3689 bool add, index, wback;
3690 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003691 case eEncodingT1:
3692 Rt = Bits32(opcode, 5, 3);
3693 Rn = Bits32(opcode, 2, 0);
3694 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3695 // index = TRUE; add = TRUE; wback = FALSE
3696 add = true;
3697 index = true;
3698 wback = false;
3699
3700 break;
3701
3702 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003703 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003704 Rt = Bits32 (opcode, 10, 8);
3705 Rn = 13;
3706 imm32 = Bits32 (opcode, 7, 0) << 2;
3707
3708 // index = TRUE; add = TRUE; wback = FALSE;
3709 index = true;
3710 add = true;
3711 wback = false;
3712
3713 break;
3714
3715 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003716 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003717 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3718 Rt = Bits32 (opcode, 15, 12);
3719 Rn = Bits32 (opcode, 19, 16);
3720 imm32 = Bits32 (opcode, 11, 0);
3721
3722 // index = TRUE; add = TRUE; wback = FALSE;
3723 index = true;
3724 add = true;
3725 wback = false;
3726
3727 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3728 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3729 return false;
3730
3731 break;
3732
3733 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003734 // if Rn == '1111' then SEE LDR (literal);
3735 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3736 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3737 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003738 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3739 return false;
3740
3741 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3742 Rt = Bits32 (opcode, 15, 12);
3743 Rn = Bits32 (opcode, 19, 16);
3744 imm32 = Bits32 (opcode, 7, 0);
3745
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003746 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003747 index = BitIsSet (opcode, 10);
3748 add = BitIsSet (opcode, 9);
3749 wback = BitIsSet (opcode, 8);
3750
3751 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3752 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3753 return false;
3754
3755 break;
3756
3757 default:
3758 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003759 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003760 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003761 if (!success)
3762 return false;
3763 if (add)
3764 offset_addr = base + imm32;
3765 else
3766 offset_addr = base - imm32;
3767
3768 address = (index ? offset_addr : base);
3769
Caroline Ticebaf1f642011-03-24 19:23:45 +00003770 Register base_reg;
3771 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003772 if (wback)
3773 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003774 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003775 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3776 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003777
Johnny Chenef21b592011-02-10 01:52:38 +00003778 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3779 return false;
3780 }
3781
3782 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003783 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003784 context.type = EmulateInstruction::eContextRegisterLoad;
3785 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003786
3787 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003788 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003789 if (!success)
3790 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003791
3792 if (Rt == 15)
3793 {
3794 if (Bits32(address, 1, 0) == 0)
3795 {
Johnny Chen668b4512011-02-15 21:08:58 +00003796 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003797 return false;
3798 }
3799 else
3800 return false;
3801 }
3802 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3803 {
3804 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3805 return false;
3806 }
3807 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003808 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003809 }
3810 return true;
3811}
3812
Caroline Ticeaf556562011-02-15 18:42:15 +00003813// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3814// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3815// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003816bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003817EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003818{
3819#if 0
3820 if ConditionPassed() then
3821 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3822 address = R[n];
3823
3824 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003825 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003826 if i == n && wback && i != LowestSetBit(registers) then
3827 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3828 else
3829 MemA[address,4] = R[i];
3830 address = address + 4;
3831
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003832 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003833 MemA[address,4] = PCStoreValue();
3834 if wback then R[n] = R[n] + 4*BitCount(registers);
3835#endif
3836
3837 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003838
Greg Clayton7bc39082011-03-24 23:53:38 +00003839 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003840 {
3841 uint32_t n;
3842 uint32_t registers = 0;
3843 bool wback;
3844 const uint32_t addr_byte_size = GetAddressByteSize();
3845
3846 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3847 switch (encoding)
3848 {
3849 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003850 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003851 n = Bits32 (opcode, 10, 8);
3852 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003853 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003854 wback = true;
3855
3856 // if BitCount(registers) < 1 then UNPREDICTABLE;
3857 if (BitCount (registers) < 1)
3858 return false;
3859
3860 break;
3861
3862 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003863 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003864 n = Bits32 (opcode, 19, 16);
3865 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003866 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003867 wback = BitIsSet (opcode, 21);
3868
3869 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3870 if ((n == 15) || (BitCount (registers) < 2))
3871 return false;
3872
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003873 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003874 if (wback && BitIsSet (registers, n))
3875 return false;
3876
3877 break;
3878
3879 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003880 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003881 n = Bits32 (opcode, 19, 16);
3882 registers = Bits32 (opcode, 15, 0);
3883 wback = BitIsSet (opcode, 21);
3884
3885 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3886 if ((n == 15) || (BitCount (registers) < 1))
3887 return false;
3888
3889 break;
3890
3891 default:
3892 return false;
3893 }
3894
3895 // address = R[n];
3896 int32_t offset = 0;
3897 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3898 if (!success)
3899 return false;
3900
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003901 EmulateInstruction::Context context;
3902 context.type = EmulateInstruction::eContextRegisterStore;
3903 Register base_reg;
3904 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003905
3906 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003907 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003908 for (int i = 0; i < 14; ++i)
3909 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003910 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003911 if (BitIsSet (registers, i))
3912 {
3913 if (i < lowest_set_bit)
3914 lowest_set_bit = i;
3915 // if i == n && wback && i != LowestSetBit(registers) then
3916 if ((i == n) && wback && (i != lowest_set_bit))
3917 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3918 WriteBits32UnknownToMemory (address + offset);
3919 else
3920 {
3921 // MemA[address,4] = R[i];
3922 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3923 if (!success)
3924 return false;
3925
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003926 Register data_reg;
3927 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3928 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003929 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003930 return false;
3931 }
3932
3933 // address = address + 4;
3934 offset += addr_byte_size;
3935 }
3936 }
3937
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003938 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003939 // MemA[address,4] = PCStoreValue();
3940 if (BitIsSet (registers, 15))
3941 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003942 Register pc_reg;
3943 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3944 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003945 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003946 if (!success)
3947 return false;
3948
Caroline Tice8d681f52011-03-17 23:50:16 +00003949 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003950 return false;
3951 }
3952
3953 // if wback then R[n] = R[n] + 4*BitCount(registers);
3954 if (wback)
3955 {
3956 offset = addr_byte_size * BitCount (registers);
3957 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003958 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003959 addr_t data = address + offset;
3960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3961 return false;
3962 }
3963 }
3964 return true;
3965}
3966
Caroline Ticeaf556562011-02-15 18:42:15 +00003967// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3968// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3969// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003970bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003971EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00003972{
3973#if 0
3974 if ConditionPassed() then
3975 EncodingSpecificOperations();
3976 address = R[n] - 4*BitCount(registers) + 4;
3977
3978 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003979 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003980 if i == n && wback && i != LowestSetBit(registers) then
3981 MemA[address,4] = bits(32) UNKNOWN;
3982 else
3983 MemA[address,4] = R[i];
3984 address = address + 4;
3985
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003986 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003987 MemA[address,4] = PCStoreValue();
3988
3989 if wback then R[n] = R[n] - 4*BitCount(registers);
3990#endif
3991
3992 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00003993
Greg Clayton7bc39082011-03-24 23:53:38 +00003994 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00003995 {
3996 uint32_t n;
3997 uint32_t registers = 0;
3998 bool wback;
3999 const uint32_t addr_byte_size = GetAddressByteSize();
4000
4001 // EncodingSpecificOperations();
4002 switch (encoding)
4003 {
4004 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004005 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004006 n = Bits32 (opcode, 19, 16);
4007 registers = Bits32 (opcode, 15, 0);
4008 wback = BitIsSet (opcode, 21);
4009
4010 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4011 if ((n == 15) || (BitCount (registers) < 1))
4012 return false;
4013 break;
4014 default:
4015 return false;
4016 }
4017
4018 // address = R[n] - 4*BitCount(registers) + 4;
4019 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004020 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004021 if (!success)
4022 return false;
4023
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004024 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004025
4026 EmulateInstruction::Context context;
4027 context.type = EmulateInstruction::eContextRegisterStore;
4028 Register base_reg;
4029 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4030
4031 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004032 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004033 for (int i = 0; i < 14; ++i)
4034 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004035 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004036 if (BitIsSet (registers, i))
4037 {
4038 if (i < lowest_bit_set)
4039 lowest_bit_set = i;
4040 //if i == n && wback && i != LowestSetBit(registers) then
4041 if ((i == n) && wback && (i != lowest_bit_set))
4042 // MemA[address,4] = bits(32) UNKNOWN;
4043 WriteBits32UnknownToMemory (address + offset);
4044 else
4045 {
4046 // MemA[address,4] = R[i];
4047 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4048 if (!success)
4049 return false;
4050
4051 Register data_reg;
4052 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004053 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004054 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004055 return false;
4056 }
4057
4058 // address = address + 4;
4059 offset += addr_byte_size;
4060 }
4061 }
4062
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004063 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004064 // MemA[address,4] = PCStoreValue();
4065 if (BitIsSet (registers, 15))
4066 {
4067 Register pc_reg;
4068 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4069 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004070 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004071 if (!success)
4072 return false;
4073
Caroline Tice8d681f52011-03-17 23:50:16 +00004074 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004075 return false;
4076 }
4077
4078 // if wback then R[n] = R[n] - 4*BitCount(registers);
4079 if (wback)
4080 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004081 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004082 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4083 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004084 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4086 return false;
4087 }
4088 }
4089 return true;
4090}
4091
Caroline Ticeaf556562011-02-15 18:42:15 +00004092// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4093// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4094// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004095bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004096EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004097{
4098#if 0
4099 if ConditionPassed() then
4100 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4101 address = R[n] - 4*BitCount(registers);
4102
4103 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004104 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004105 if i == n && wback && i != LowestSetBit(registers) then
4106 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4107 else
4108 MemA[address,4] = R[i];
4109 address = address + 4;
4110
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004111 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004112 MemA[address,4] = PCStoreValue();
4113
4114 if wback then R[n] = R[n] - 4*BitCount(registers);
4115#endif
4116
4117
4118 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004119
Greg Clayton7bc39082011-03-24 23:53:38 +00004120 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004121 {
4122 uint32_t n;
4123 uint32_t registers = 0;
4124 bool wback;
4125 const uint32_t addr_byte_size = GetAddressByteSize();
4126
4127 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4128 switch (encoding)
4129 {
4130 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004131 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004132 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4133 {
4134 // See PUSH
4135 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004136 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004137 n = Bits32 (opcode, 19, 16);
4138 registers = Bits32 (opcode, 15, 0);
4139 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4140 wback = BitIsSet (opcode, 21);
4141 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4142 if ((n == 15) || BitCount (registers) < 2)
4143 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004144 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004145 if (wback && BitIsSet (registers, n))
4146 return false;
4147 break;
4148
4149 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004150 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004151 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4152 {
4153 // See Push
4154 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004155 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004156 n = Bits32 (opcode, 19, 16);
4157 registers = Bits32 (opcode, 15, 0);
4158 wback = BitIsSet (opcode, 21);
4159 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4160 if ((n == 15) || BitCount (registers) < 1)
4161 return false;
4162 break;
4163
4164 default:
4165 return false;
4166 }
4167
4168 // address = R[n] - 4*BitCount(registers);
4169
4170 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004171 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004172 if (!success)
4173 return false;
4174
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004175 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004176
4177 EmulateInstruction::Context context;
4178 context.type = EmulateInstruction::eContextRegisterStore;
4179 Register base_reg;
4180 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4181
4182 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004183 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004184 for (int i = 0; i < 14; ++i)
4185 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004186 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004187 if (BitIsSet (registers, i))
4188 {
4189 if (i < lowest_set_bit)
4190 lowest_set_bit = i;
4191 // if i == n && wback && i != LowestSetBit(registers) then
4192 if ((i == n) && wback && (i != lowest_set_bit))
4193 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4194 WriteBits32UnknownToMemory (address + offset);
4195 else
4196 {
4197 // MemA[address,4] = R[i];
4198 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4199 if (!success)
4200 return false;
4201
4202 Register data_reg;
4203 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004204 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004205 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004206 return false;
4207 }
4208
4209 // address = address + 4;
4210 offset += addr_byte_size;
4211 }
4212 }
4213
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004214 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004215 // MemA[address,4] = PCStoreValue();
4216 if (BitIsSet (registers, 15))
4217 {
4218 Register pc_reg;
4219 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4220 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004221 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004222 if (!success)
4223 return false;
4224
Caroline Tice8d681f52011-03-17 23:50:16 +00004225 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004226 return false;
4227 }
4228
4229 // if wback then R[n] = R[n] - 4*BitCount(registers);
4230 if (wback)
4231 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004232 offset = (addr_byte_size * BitCount (registers)) * -1;
4233 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4234 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004235 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004236 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4237 return false;
4238 }
4239 }
4240 return true;
4241}
4242
4243// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4244// from a base register. The consecutive memory locations start just above this address, and the address of the last
4245// of those locations can optionally be written back to the base register.
4246bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004247EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004248{
4249#if 0
4250 if ConditionPassed() then
4251 EncodingSpecificOperations();
4252 address = R[n] + 4;
4253
4254 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004255 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004256 if i == n && wback && i != LowestSetBit(registers) then
4257 MemA[address,4] = bits(32) UNKNOWN;
4258 else
4259 MemA[address,4] = R[i];
4260 address = address + 4;
4261
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004262 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004263 MemA[address,4] = PCStoreValue();
4264
4265 if wback then R[n] = R[n] + 4*BitCount(registers);
4266#endif
4267
4268 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004269
Greg Clayton7bc39082011-03-24 23:53:38 +00004270 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004271 {
4272 uint32_t n;
4273 uint32_t registers = 0;
4274 bool wback;
4275 const uint32_t addr_byte_size = GetAddressByteSize();
4276
4277 // EncodingSpecificOperations();
4278 switch (encoding)
4279 {
4280 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004281 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004282 n = Bits32 (opcode, 19, 16);
4283 registers = Bits32 (opcode, 15, 0);
4284 wback = BitIsSet (opcode, 21);
4285
4286 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4287 if ((n == 15) && (BitCount (registers) < 1))
4288 return false;
4289 break;
4290 default:
4291 return false;
4292 }
4293 // address = R[n] + 4;
4294
4295 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004296 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004297 if (!success)
4298 return false;
4299
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004300 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004301
4302 EmulateInstruction::Context context;
4303 context.type = EmulateInstruction::eContextRegisterStore;
4304 Register base_reg;
4305 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4306
4307 uint32_t lowest_set_bit = 14;
4308 // for i = 0 to 14
4309 for (int i = 0; i < 14; ++i)
4310 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004311 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004312 if (BitIsSet (registers, i))
4313 {
4314 if (i < lowest_set_bit)
4315 lowest_set_bit = i;
4316 // if i == n && wback && i != LowestSetBit(registers) then
4317 if ((i == n) && wback && (i != lowest_set_bit))
4318 // MemA[address,4] = bits(32) UNKNOWN;
4319 WriteBits32UnknownToMemory (address + offset);
4320 // else
4321 else
4322 {
4323 // MemA[address,4] = R[i];
4324 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4325 if (!success)
4326 return false;
4327
4328 Register data_reg;
4329 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004330 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004331 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004332 return false;
4333 }
4334
4335 // address = address + 4;
4336 offset += addr_byte_size;
4337 }
4338 }
4339
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004340 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004341 // MemA[address,4] = PCStoreValue();
4342 if (BitIsSet (registers, 15))
4343 {
4344 Register pc_reg;
4345 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4346 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004347 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004348 if (!success)
4349 return false;
4350
Caroline Tice8d681f52011-03-17 23:50:16 +00004351 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004352 return false;
4353 }
4354
4355 // if wback then R[n] = R[n] + 4*BitCount(registers);
4356 if (wback)
4357 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004358 offset = addr_byte_size * BitCount (registers);
4359 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4360 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004361 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4363 return false;
4364 }
4365 }
4366 return true;
4367}
Caroline Tice7fac8572011-02-15 22:53:54 +00004368
4369// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4370// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4371bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004372EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004373{
4374#if 0
4375 if ConditionPassed() then
4376 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4377 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4378 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004379 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004380 MemU[address,4] = R[t];
4381 else // Can only occur before ARMv7
4382 MemU[address,4] = bits(32) UNKNOWN;
4383 if wback then R[n] = offset_addr;
4384#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004385
Caroline Tice7fac8572011-02-15 22:53:54 +00004386 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004387
Greg Clayton7bc39082011-03-24 23:53:38 +00004388 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004389 {
4390 const uint32_t addr_byte_size = GetAddressByteSize();
4391
4392 uint32_t t;
4393 uint32_t n;
4394 uint32_t imm32;
4395 bool index;
4396 bool add;
4397 bool wback;
4398 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4399 switch (encoding)
4400 {
4401 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004402 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004403 t = Bits32 (opcode, 2, 0);
4404 n = Bits32 (opcode, 5, 3);
4405 imm32 = Bits32 (opcode, 10, 6) << 2;
4406
4407 // index = TRUE; add = TRUE; wback = FALSE;
4408 index = true;
4409 add = false;
4410 wback = false;
4411 break;
4412
4413 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004414 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004415 t = Bits32 (opcode, 10, 8);
4416 n = 13;
4417 imm32 = Bits32 (opcode, 7, 0) << 2;
4418
4419 // index = TRUE; add = TRUE; wback = FALSE;
4420 index = true;
4421 add = true;
4422 wback = false;
4423 break;
4424
4425 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004426 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004427 if (Bits32 (opcode, 19, 16) == 15)
4428 return false;
4429
4430 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4431 t = Bits32 (opcode, 15, 12);
4432 n = Bits32 (opcode, 19, 16);
4433 imm32 = Bits32 (opcode, 11, 0);
4434
4435 // index = TRUE; add = TRUE; wback = FALSE;
4436 index = true;
4437 add = true;
4438 wback = false;
4439
4440 // if t == 15 then UNPREDICTABLE;
4441 if (t == 15)
4442 return false;
4443 break;
4444
4445 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004446 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4447 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4448 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004449 if ((Bits32 (opcode, 19, 16) == 15)
4450 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4451 return false;
4452
4453 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4454 t = Bits32 (opcode, 15, 12);
4455 n = Bits32 (opcode, 19, 16);
4456 imm32 = Bits32 (opcode, 7, 0);
4457
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004458 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004459 index = BitIsSet (opcode, 10);
4460 add = BitIsSet (opcode, 9);
4461 wback = BitIsSet (opcode, 8);
4462
4463 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4464 if ((t == 15) || (wback && (n == t)))
4465 return false;
4466 break;
4467
4468 default:
4469 return false;
4470 }
4471
4472 addr_t offset_addr;
4473 addr_t address;
4474
4475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004476 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004477 if (!success)
4478 return false;
4479
4480 if (add)
4481 offset_addr = base_address + imm32;
4482 else
4483 offset_addr = base_address - imm32;
4484
4485 // address = if index then offset_addr else R[n];
4486 if (index)
4487 address = offset_addr;
4488 else
4489 address = base_address;
4490
4491 EmulateInstruction::Context context;
4492 context.type = eContextRegisterStore;
4493 Register base_reg;
4494 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4495
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004496 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004497 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4498 {
4499 // MemU[address,4] = R[t];
4500 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4501 if (!success)
4502 return false;
4503
4504 Register data_reg;
4505 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4506 int32_t offset = address - base_address;
4507 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004508 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004509 return false;
4510 }
4511 else
4512 {
4513 // MemU[address,4] = bits(32) UNKNOWN;
4514 WriteBits32UnknownToMemory (address);
4515 }
4516
4517 // if wback then R[n] = offset_addr;
4518 if (wback)
4519 {
4520 context.type = eContextRegisterLoad;
4521 context.SetAddress (offset_addr);
4522 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4523 return false;
4524 }
4525 }
4526 return true;
4527}
Caroline Ticeaf556562011-02-15 18:42:15 +00004528
Caroline Tice3fd63e92011-02-16 00:33:43 +00004529// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4530// word from a register to memory. The offset register value can optionally be shifted.
4531bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004532EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004533{
4534#if 0
4535 if ConditionPassed() then
4536 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4537 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4538 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4539 address = if index then offset_addr else R[n];
4540 if t == 15 then // Only possible for encoding A1
4541 data = PCStoreValue();
4542 else
4543 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004544 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004545 MemU[address,4] = data;
4546 else // Can only occur before ARMv7
4547 MemU[address,4] = bits(32) UNKNOWN;
4548 if wback then R[n] = offset_addr;
4549#endif
4550
4551 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004552
Greg Clayton7bc39082011-03-24 23:53:38 +00004553 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004554 {
4555 const uint32_t addr_byte_size = GetAddressByteSize();
4556
4557 uint32_t t;
4558 uint32_t n;
4559 uint32_t m;
4560 ARM_ShifterType shift_t;
4561 uint32_t shift_n;
4562 bool index;
4563 bool add;
4564 bool wback;
4565
4566 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4567 switch (encoding)
4568 {
4569 case eEncodingT1:
4570 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4571 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4572 t = Bits32 (opcode, 2, 0);
4573 n = Bits32 (opcode, 5, 3);
4574 m = Bits32 (opcode, 8, 6);
4575
4576 // index = TRUE; add = TRUE; wback = FALSE;
4577 index = true;
4578 add = true;
4579 wback = false;
4580
4581 // (shift_t, shift_n) = (SRType_LSL, 0);
4582 shift_t = SRType_LSL;
4583 shift_n = 0;
4584 break;
4585
4586 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004587 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004588 if (Bits32 (opcode, 19, 16) == 15)
4589 return false;
4590
4591 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4592 t = Bits32 (opcode, 15, 12);
4593 n = Bits32 (opcode, 19, 16);
4594 m = Bits32 (opcode, 3, 0);
4595
4596 // index = TRUE; add = TRUE; wback = FALSE;
4597 index = true;
4598 add = true;
4599 wback = false;
4600
4601 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4602 shift_t = SRType_LSL;
4603 shift_n = Bits32 (opcode, 5, 4);
4604
4605 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4606 if ((t == 15) || (BadReg (m)))
4607 return false;
4608 break;
4609
4610 case eEncodingA1:
4611 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004612 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004613 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4614 t = Bits32 (opcode, 15, 12);
4615 n = Bits32 (opcode, 19, 16);
4616 m = Bits32 (opcode, 3, 0);
4617
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004618 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004619 index = BitIsSet (opcode, 24);
4620 add = BitIsSet (opcode, 23);
4621 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4622
4623 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4624 uint32_t typ = Bits32 (opcode, 6, 5);
4625 uint32_t imm5 = Bits32 (opcode, 11, 7);
4626 shift_n = DecodeImmShift(typ, imm5, shift_t);
4627
4628 // if m == 15 then UNPREDICTABLE;
4629 if (m == 15)
4630 return false;
4631
4632 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4633 if (wback && ((n == 15) || (n == t)))
4634 return false;
4635
4636 break;
4637 }
4638 default:
4639 return false;
4640 }
4641
4642 addr_t offset_addr;
4643 addr_t address;
4644 int32_t offset = 0;
4645
4646 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4647 if (!success)
4648 return false;
4649
4650 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4651 if (!success)
4652 return false;
4653
4654 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004655 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004656
4657 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4658 if (add)
4659 offset_addr = base_address + offset;
4660 else
4661 offset_addr = base_address - offset;
4662
4663 // address = if index then offset_addr else R[n];
4664 if (index)
4665 address = offset_addr;
4666 else
4667 address = base_address;
4668
4669 uint32_t data;
4670 // if t == 15 then // Only possible for encoding A1
4671 if (t == 15)
4672 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004673 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004674 else
4675 // data = R[t];
4676 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4677
4678 if (!success)
4679 return false;
4680
4681 EmulateInstruction::Context context;
4682 context.type = eContextRegisterStore;
4683
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004684 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004685 if (UnalignedSupport ()
4686 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4687 || CurrentInstrSet() == eModeARM)
4688 {
4689 // MemU[address,4] = data;
4690
4691 Register base_reg;
4692 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4693
4694 Register data_reg;
4695 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4696
4697 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004698 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004699 return false;
4700
4701 }
4702 else
4703 // MemU[address,4] = bits(32) UNKNOWN;
4704 WriteBits32UnknownToMemory (address);
4705
4706 // if wback then R[n] = offset_addr;
4707 if (wback)
4708 {
4709 context.type = eContextRegisterLoad;
4710 context.SetAddress (offset_addr);
4711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4712 return false;
4713 }
4714
4715 }
4716 return true;
4717}
Caroline Tice73a29de2011-02-16 20:22:22 +00004718
4719bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004720EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004721{
4722#if 0
4723 if ConditionPassed() then
4724 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4726 address = if index then offset_addr else R[n];
4727 MemU[address,1] = R[t]<7:0>;
4728 if wback then R[n] = offset_addr;
4729#endif
4730
4731
4732 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004733
Greg Clayton7bc39082011-03-24 23:53:38 +00004734 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004735 {
4736 uint32_t t;
4737 uint32_t n;
4738 uint32_t imm32;
4739 bool index;
4740 bool add;
4741 bool wback;
4742 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4743 switch (encoding)
4744 {
4745 case eEncodingT1:
4746 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4747 t = Bits32 (opcode, 2, 0);
4748 n = Bits32 (opcode, 5, 3);
4749 imm32 = Bits32 (opcode, 10, 6);
4750
4751 // index = TRUE; add = TRUE; wback = FALSE;
4752 index = true;
4753 add = true;
4754 wback = false;
4755 break;
4756
4757 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004758 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004759 if (Bits32 (opcode, 19, 16) == 15)
4760 return false;
4761
4762 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4763 t = Bits32 (opcode, 15, 12);
4764 n = Bits32 (opcode, 19, 16);
4765 imm32 = Bits32 (opcode, 11, 0);
4766
4767 // index = TRUE; add = TRUE; wback = FALSE;
4768 index = true;
4769 add = true;
4770 wback = false;
4771
4772 // if BadReg(t) then UNPREDICTABLE;
4773 if (BadReg (t))
4774 return false;
4775 break;
4776
4777 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004778 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4779 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004780 if (Bits32 (opcode, 19, 16) == 15)
4781 return false;
4782
4783 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4784 t = Bits32 (opcode, 15, 12);
4785 n = Bits32 (opcode, 19, 16);
4786 imm32 = Bits32 (opcode, 7, 0);
4787
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004788 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004789 index = BitIsSet (opcode, 10);
4790 add = BitIsSet (opcode, 9);
4791 wback = BitIsSet (opcode, 8);
4792
4793 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4794 if ((BadReg (t)) || (wback && (n == t)))
4795 return false;
4796 break;
4797
4798 default:
4799 return false;
4800 }
4801
4802 addr_t offset_addr;
4803 addr_t address;
4804 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4805 if (!success)
4806 return false;
4807
4808 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4809 if (add)
4810 offset_addr = base_address + imm32;
4811 else
4812 offset_addr = base_address - imm32;
4813
4814 // address = if index then offset_addr else R[n];
4815 if (index)
4816 address = offset_addr;
4817 else
4818 address = base_address;
4819
Caroline Ticecc96eb52011-02-17 19:20:40 +00004820 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004821 Register base_reg;
4822 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4823
4824 Register data_reg;
4825 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4826
4827 EmulateInstruction::Context context;
4828 context.type = eContextRegisterStore;
4829 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4830
4831 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4832 if (!success)
4833 return false;
4834
4835 data = Bits32 (data, 7, 0);
4836
Caroline Ticecc96eb52011-02-17 19:20:40 +00004837 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004838 return false;
4839
4840 // if wback then R[n] = offset_addr;
4841 if (wback)
4842 {
4843 context.type = eContextRegisterLoad;
4844 context.SetAddress (offset_addr);
4845 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4846 return false;
4847 }
4848
4849 }
4850
4851 return true;
4852}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004853
4854// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4855// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4856bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004857EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004858{
4859#if 0
4860 if ConditionPassed() then
4861 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4862 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4863 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4864 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004865 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004866 MemU[address,2] = R[t]<15:0>;
4867 else // Can only occur before ARMv7
4868 MemU[address,2] = bits(16) UNKNOWN;
4869 if wback then R[n] = offset_addr;
4870#endif
4871
4872 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004873
Greg Clayton7bc39082011-03-24 23:53:38 +00004874 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004875 {
4876 uint32_t t;
4877 uint32_t n;
4878 uint32_t m;
4879 bool index;
4880 bool add;
4881 bool wback;
4882 ARM_ShifterType shift_t;
4883 uint32_t shift_n;
4884
4885 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4886 switch (encoding)
4887 {
4888 case eEncodingT1:
4889 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4890 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4891 t = Bits32 (opcode, 2, 0);
4892 n = Bits32 (opcode, 5, 3);
4893 m = Bits32 (opcode, 8, 6);
4894
4895 // index = TRUE; add = TRUE; wback = FALSE;
4896 index = true;
4897 add = true;
4898 wback = false;
4899
4900 // (shift_t, shift_n) = (SRType_LSL, 0);
4901 shift_t = SRType_LSL;
4902 shift_n = 0;
4903
4904 break;
4905
4906 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004907 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004908 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4909 t = Bits32 (opcode, 15, 12);
4910 n = Bits32 (opcode, 19, 16);
4911 m = Bits32 (opcode, 3, 0);
4912 if (n == 15)
4913 return false;
4914
4915 // index = TRUE; add = TRUE; wback = FALSE;
4916 index = true;
4917 add = true;
4918 wback = false;
4919
4920 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4921 shift_t = SRType_LSL;
4922 shift_n = Bits32 (opcode, 5, 4);
4923
4924 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4925 if (BadReg (t) || BadReg (m))
4926 return false;
4927
4928 break;
4929
4930 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004931 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004932 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4933 t = Bits32 (opcode, 15, 12);
4934 n = Bits32 (opcode, 19, 16);
4935 m = Bits32 (opcode, 3, 0);
4936
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004937 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004938 index = BitIsSet (opcode, 24);
4939 add = BitIsSet (opcode, 23);
4940 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4941
4942 // (shift_t, shift_n) = (SRType_LSL, 0);
4943 shift_t = SRType_LSL;
4944 shift_n = 0;
4945
4946 // if t == 15 || m == 15 then UNPREDICTABLE;
4947 if ((t == 15) || (m == 15))
4948 return false;
4949
4950 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4951 if (wback && ((n == 15) || (n == t)))
4952 return false;
4953
4954 break;
4955
4956 default:
4957 return false;
4958 }
4959
4960 uint32_t Rm = ReadCoreReg (m, &success);
4961 if (!success)
4962 return false;
4963
4964 uint32_t Rn = ReadCoreReg (n, &success);
4965 if (!success)
4966 return false;
4967
4968 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4969 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4970
4971 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4972 addr_t offset_addr;
4973 if (add)
4974 offset_addr = Rn + offset;
4975 else
4976 offset_addr = Rn - offset;
4977
4978 // address = if index then offset_addr else R[n];
4979 addr_t address;
4980 if (index)
4981 address = offset_addr;
4982 else
4983 address = Rn;
4984
4985 EmulateInstruction::Context context;
4986 context.type = eContextRegisterStore;
4987 Register base_reg;
4988 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4989 Register offset_reg;
4990 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4991
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004992 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004993 if (UnalignedSupport() || BitIsClear (address, 0))
4994 {
4995 // MemU[address,2] = R[t]<15:0>;
4996 uint32_t Rt = ReadCoreReg (t, &success);
4997 if (!success)
4998 return false;
4999
5000 EmulateInstruction::Context context;
5001 context.type = eContextRegisterStore;
5002 Register base_reg;
5003 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5004 Register offset_reg;
5005 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5006 Register data_reg;
5007 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5008 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5009
5010 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5011 return false;
5012 }
5013 else // Can only occur before ARMv7
5014 {
5015 // MemU[address,2] = bits(16) UNKNOWN;
5016 }
5017
5018 // if wback then R[n] = offset_addr;
5019 if (wback)
5020 {
5021 context.type = eContextAdjustBaseRegister;
5022 context.SetAddress (offset_addr);
5023 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5024 return false;
5025 }
5026 }
5027
5028 return true;
5029}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005030
Johnny Chen157b9592011-02-18 21:13:05 +00005031// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5032// and writes the result to the destination register. It can optionally update the condition flags
5033// based on the result.
5034bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005035EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005036{
5037#if 0
5038 // ARM pseudo code...
5039 if ConditionPassed() then
5040 EncodingSpecificOperations();
5041 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5042 if d == 15 then // Can only occur for ARM encoding
5043 ALUWritePC(result); // setflags is always FALSE here
5044 else
5045 R[d] = result;
5046 if setflags then
5047 APSR.N = result<31>;
5048 APSR.Z = IsZeroBit(result);
5049 APSR.C = carry;
5050 APSR.V = overflow;
5051#endif
5052
5053 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005054
Greg Clayton7bc39082011-03-24 23:53:38 +00005055 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005056 {
5057 uint32_t Rd, Rn;
5058 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5059 bool setflags;
5060 switch (encoding)
5061 {
5062 case eEncodingT1:
5063 Rd = Bits32(opcode, 11, 8);
5064 Rn = Bits32(opcode, 19, 16);
5065 setflags = BitIsSet(opcode, 20);
5066 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5067 if (BadReg(Rd) || BadReg(Rn))
5068 return false;
5069 break;
5070 case eEncodingA1:
5071 Rd = Bits32(opcode, 15, 12);
5072 Rn = Bits32(opcode, 19, 16);
5073 setflags = BitIsSet(opcode, 20);
5074 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5075 // TODO: Emulate SUBS PC, LR and related instructions.
5076 if (Rd == 15 && setflags)
5077 return false;
5078 break;
5079 default:
5080 return false;
5081 }
5082
5083 // Read the first operand.
5084 int32_t val1 = ReadCoreReg(Rn, &success);
5085 if (!success)
5086 return false;
5087
5088 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5089
5090 EmulateInstruction::Context context;
5091 context.type = EmulateInstruction::eContextImmediate;
5092 context.SetNoArgs ();
5093
5094 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5095 return false;
5096 }
5097 return true;
5098}
5099
5100// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5101// register value, and writes the result to the destination register. It can optionally update the
5102// condition flags based on the result.
5103bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005104EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005105{
5106#if 0
5107 // ARM pseudo code...
5108 if ConditionPassed() then
5109 EncodingSpecificOperations();
5110 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5111 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5112 if d == 15 then // Can only occur for ARM encoding
5113 ALUWritePC(result); // setflags is always FALSE here
5114 else
5115 R[d] = result;
5116 if setflags then
5117 APSR.N = result<31>;
5118 APSR.Z = IsZeroBit(result);
5119 APSR.C = carry;
5120 APSR.V = overflow;
5121#endif
5122
5123 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005124
Greg Clayton7bc39082011-03-24 23:53:38 +00005125 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005126 {
5127 uint32_t Rd, Rn, Rm;
5128 ARM_ShifterType shift_t;
5129 uint32_t shift_n; // the shift applied to the value read from Rm
5130 bool setflags;
5131 switch (encoding)
5132 {
5133 case eEncodingT1:
5134 Rd = Rn = Bits32(opcode, 2, 0);
5135 Rm = Bits32(opcode, 5, 3);
5136 setflags = !InITBlock();
5137 shift_t = SRType_LSL;
5138 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005139 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005140 case eEncodingT2:
5141 Rd = Bits32(opcode, 11, 8);
5142 Rn = Bits32(opcode, 19, 16);
5143 Rm = Bits32(opcode, 3, 0);
5144 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005145 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005146 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5147 return false;
5148 break;
5149 case eEncodingA1:
5150 Rd = Bits32(opcode, 15, 12);
5151 Rn = Bits32(opcode, 19, 16);
5152 Rm = Bits32(opcode, 3, 0);
5153 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005154 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005155 // TODO: Emulate SUBS PC, LR and related instructions.
5156 if (Rd == 15 && setflags)
5157 return false;
5158 break;
5159 default:
5160 return false;
5161 }
5162
5163 // Read the first operand.
5164 int32_t val1 = ReadCoreReg(Rn, &success);
5165 if (!success)
5166 return false;
5167
5168 // Read the second operand.
5169 int32_t val2 = ReadCoreReg(Rm, &success);
5170 if (!success)
5171 return false;
5172
5173 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5174 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5175
5176 EmulateInstruction::Context context;
5177 context.type = EmulateInstruction::eContextImmediate;
5178 context.SetNoArgs ();
5179
5180 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5181 return false;
5182 }
5183 return true;
5184}
5185
Johnny Chena695f952011-02-23 21:24:25 +00005186// This instruction adds an immediate value to the PC value to form a PC-relative address,
5187// and writes the result to the destination register.
5188bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005189EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005190{
5191#if 0
5192 // ARM pseudo code...
5193 if ConditionPassed() then
5194 EncodingSpecificOperations();
5195 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5196 if d == 15 then // Can only occur for ARM encodings
5197 ALUWritePC(result);
5198 else
5199 R[d] = result;
5200#endif
5201
5202 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005203
Greg Clayton7bc39082011-03-24 23:53:38 +00005204 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005205 {
5206 uint32_t Rd;
5207 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5208 bool add;
5209 switch (encoding)
5210 {
5211 case eEncodingT1:
5212 Rd = Bits32(opcode, 10, 8);
5213 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5214 break;
5215 case eEncodingT2:
5216 case eEncodingT3:
5217 Rd = Bits32(opcode, 11, 8);
5218 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5219 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5220 if (BadReg(Rd))
5221 return false;
5222 break;
5223 case eEncodingA1:
5224 case eEncodingA2:
5225 Rd = Bits32(opcode, 15, 12);
5226 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5227 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5228 break;
5229 default:
5230 return false;
5231 }
5232
5233 // Read the PC value.
5234 uint32_t pc = ReadCoreReg(PC_REG, &success);
5235 if (!success)
5236 return false;
5237
5238 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5239
5240 EmulateInstruction::Context context;
5241 context.type = EmulateInstruction::eContextImmediate;
5242 context.SetNoArgs ();
5243
5244 if (!WriteCoreReg(context, result, Rd))
5245 return false;
5246 }
5247 return true;
5248}
5249
Johnny Chene97c0d52011-02-18 19:32:20 +00005250// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5251// to the destination register. It can optionally update the condition flags based on the result.
5252bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005253EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005254{
5255#if 0
5256 // ARM pseudo code...
5257 if ConditionPassed() then
5258 EncodingSpecificOperations();
5259 result = R[n] AND imm32;
5260 if d == 15 then // Can only occur for ARM encoding
5261 ALUWritePC(result); // setflags is always FALSE here
5262 else
5263 R[d] = result;
5264 if setflags then
5265 APSR.N = result<31>;
5266 APSR.Z = IsZeroBit(result);
5267 APSR.C = carry;
5268 // APSR.V unchanged
5269#endif
5270
5271 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005272
Greg Clayton7bc39082011-03-24 23:53:38 +00005273 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005274 {
5275 uint32_t Rd, Rn;
5276 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5277 bool setflags;
5278 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5279 switch (encoding)
5280 {
5281 case eEncodingT1:
5282 Rd = Bits32(opcode, 11, 8);
5283 Rn = Bits32(opcode, 19, 16);
5284 setflags = BitIsSet(opcode, 20);
5285 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005286 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005287 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005288 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005289 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5290 return false;
5291 break;
5292 case eEncodingA1:
5293 Rd = Bits32(opcode, 15, 12);
5294 Rn = Bits32(opcode, 19, 16);
5295 setflags = BitIsSet(opcode, 20);
5296 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5297 // TODO: Emulate SUBS PC, LR and related instructions.
5298 if (Rd == 15 && setflags)
5299 return false;
5300 break;
5301 default:
5302 return false;
5303 }
5304
Johnny Chene97c0d52011-02-18 19:32:20 +00005305 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005306 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005307 if (!success)
5308 return false;
5309
5310 uint32_t result = val1 & imm32;
5311
5312 EmulateInstruction::Context context;
5313 context.type = EmulateInstruction::eContextImmediate;
5314 context.SetNoArgs ();
5315
5316 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5317 return false;
5318 }
5319 return true;
5320}
5321
5322// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5323// and writes the result to the destination register. It can optionally update the condition flags
5324// based on the result.
5325bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005326EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005327{
5328#if 0
5329 // ARM pseudo code...
5330 if ConditionPassed() then
5331 EncodingSpecificOperations();
5332 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5333 result = R[n] AND shifted;
5334 if d == 15 then // Can only occur for ARM encoding
5335 ALUWritePC(result); // setflags is always FALSE here
5336 else
5337 R[d] = result;
5338 if setflags then
5339 APSR.N = result<31>;
5340 APSR.Z = IsZeroBit(result);
5341 APSR.C = carry;
5342 // APSR.V unchanged
5343#endif
5344
5345 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005346
Greg Clayton7bc39082011-03-24 23:53:38 +00005347 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005348 {
5349 uint32_t Rd, Rn, Rm;
5350 ARM_ShifterType shift_t;
5351 uint32_t shift_n; // the shift applied to the value read from Rm
5352 bool setflags;
5353 uint32_t carry;
5354 switch (encoding)
5355 {
5356 case eEncodingT1:
5357 Rd = Rn = Bits32(opcode, 2, 0);
5358 Rm = Bits32(opcode, 5, 3);
5359 setflags = !InITBlock();
5360 shift_t = SRType_LSL;
5361 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005362 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005363 case eEncodingT2:
5364 Rd = Bits32(opcode, 11, 8);
5365 Rn = Bits32(opcode, 19, 16);
5366 Rm = Bits32(opcode, 3, 0);
5367 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005368 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005369 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005370 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005371 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005372 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5373 return false;
5374 break;
5375 case eEncodingA1:
5376 Rd = Bits32(opcode, 15, 12);
5377 Rn = Bits32(opcode, 19, 16);
5378 Rm = Bits32(opcode, 3, 0);
5379 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005380 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005381 // TODO: Emulate SUBS PC, LR and related instructions.
5382 if (Rd == 15 && setflags)
5383 return false;
5384 break;
5385 default:
5386 return false;
5387 }
5388
Johnny Chene97c0d52011-02-18 19:32:20 +00005389 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005390 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005391 if (!success)
5392 return false;
5393
5394 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005395 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005396 if (!success)
5397 return false;
5398
5399 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5400 uint32_t result = val1 & shifted;
5401
5402 EmulateInstruction::Context context;
5403 context.type = EmulateInstruction::eContextImmediate;
5404 context.SetNoArgs ();
5405
5406 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5407 return false;
5408 }
5409 return true;
5410}
5411
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005412// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5413// immediate value, and writes the result to the destination register. It can optionally update the
5414// condition flags based on the result.
5415bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005416EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005417{
5418#if 0
5419 // ARM pseudo code...
5420 if ConditionPassed() then
5421 EncodingSpecificOperations();
5422 result = R[n] AND NOT(imm32);
5423 if d == 15 then // Can only occur for ARM encoding
5424 ALUWritePC(result); // setflags is always FALSE here
5425 else
5426 R[d] = result;
5427 if setflags then
5428 APSR.N = result<31>;
5429 APSR.Z = IsZeroBit(result);
5430 APSR.C = carry;
5431 // APSR.V unchanged
5432#endif
5433
5434 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005435
Greg Clayton7bc39082011-03-24 23:53:38 +00005436 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005437 {
5438 uint32_t Rd, Rn;
5439 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5440 bool setflags;
5441 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5442 switch (encoding)
5443 {
5444 case eEncodingT1:
5445 Rd = Bits32(opcode, 11, 8);
5446 Rn = Bits32(opcode, 19, 16);
5447 setflags = BitIsSet(opcode, 20);
5448 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5449 if (BadReg(Rd) || BadReg(Rn))
5450 return false;
5451 break;
5452 case eEncodingA1:
5453 Rd = Bits32(opcode, 15, 12);
5454 Rn = Bits32(opcode, 19, 16);
5455 setflags = BitIsSet(opcode, 20);
5456 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005457 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005458 // TODO: Emulate SUBS PC, LR and related instructions.
5459 if (Rd == 15 && setflags)
5460 return false;
5461 break;
5462 default:
5463 return false;
5464 }
5465
5466 // Read the first operand.
5467 uint32_t val1 = ReadCoreReg(Rn, &success);
5468 if (!success)
5469 return false;
5470
5471 uint32_t result = val1 & ~imm32;
5472
5473 EmulateInstruction::Context context;
5474 context.type = EmulateInstruction::eContextImmediate;
5475 context.SetNoArgs ();
5476
5477 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5478 return false;
5479 }
5480 return true;
5481}
5482
5483// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5484// optionally-shifted register value, and writes the result to the destination register.
5485// It can optionally update the condition flags based on the result.
5486bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005487EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005488{
5489#if 0
5490 // ARM pseudo code...
5491 if ConditionPassed() then
5492 EncodingSpecificOperations();
5493 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5494 result = R[n] AND NOT(shifted);
5495 if d == 15 then // Can only occur for ARM encoding
5496 ALUWritePC(result); // setflags is always FALSE here
5497 else
5498 R[d] = result;
5499 if setflags then
5500 APSR.N = result<31>;
5501 APSR.Z = IsZeroBit(result);
5502 APSR.C = carry;
5503 // APSR.V unchanged
5504#endif
5505
5506 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005507
Greg Clayton7bc39082011-03-24 23:53:38 +00005508 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005509 {
5510 uint32_t Rd, Rn, Rm;
5511 ARM_ShifterType shift_t;
5512 uint32_t shift_n; // the shift applied to the value read from Rm
5513 bool setflags;
5514 uint32_t carry;
5515 switch (encoding)
5516 {
5517 case eEncodingT1:
5518 Rd = Rn = Bits32(opcode, 2, 0);
5519 Rm = Bits32(opcode, 5, 3);
5520 setflags = !InITBlock();
5521 shift_t = SRType_LSL;
5522 shift_n = 0;
5523 break;
5524 case eEncodingT2:
5525 Rd = Bits32(opcode, 11, 8);
5526 Rn = Bits32(opcode, 19, 16);
5527 Rm = Bits32(opcode, 3, 0);
5528 setflags = BitIsSet(opcode, 20);
5529 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5530 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5531 return false;
5532 break;
5533 case eEncodingA1:
5534 Rd = Bits32(opcode, 15, 12);
5535 Rn = Bits32(opcode, 19, 16);
5536 Rm = Bits32(opcode, 3, 0);
5537 setflags = BitIsSet(opcode, 20);
5538 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005539 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005540 // TODO: Emulate SUBS PC, LR and related instructions.
5541 if (Rd == 15 && setflags)
5542 return false;
5543 break;
5544 default:
5545 return false;
5546 }
5547
5548 // Read the first operand.
5549 uint32_t val1 = ReadCoreReg(Rn, &success);
5550 if (!success)
5551 return false;
5552
5553 // Read the second operand.
5554 uint32_t val2 = ReadCoreReg(Rm, &success);
5555 if (!success)
5556 return false;
5557
5558 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5559 uint32_t result = val1 & ~shifted;
5560
5561 EmulateInstruction::Context context;
5562 context.type = EmulateInstruction::eContextImmediate;
5563 context.SetNoArgs ();
5564
5565 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5566 return false;
5567 }
5568 return true;
5569}
5570
Caroline Tice4d729c52011-02-18 00:55:53 +00005571// 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 +00005572// 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 +00005573bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005574EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005575{
5576#if 0
5577 if ConditionPassed() then
5578 EncodingSpecificOperations();
5579 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5580 address = if index then offset_addr else R[n];
5581 data = MemU[address,4];
5582 if wback then R[n] = offset_addr;
5583 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005584 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5585 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005586 R[t] = data;
5587 else // Can only apply before ARMv7
5588 R[t] = ROR(data, 8*UInt(address<1:0>));
5589#endif
5590
5591 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005592
Greg Clayton7bc39082011-03-24 23:53:38 +00005593 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005594 {
5595 const uint32_t addr_byte_size = GetAddressByteSize();
5596
5597 uint32_t t;
5598 uint32_t n;
5599 uint32_t imm32;
5600 bool index;
5601 bool add;
5602 bool wback;
5603
5604 switch (encoding)
5605 {
5606 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005607 // if Rn == '1111' then SEE LDR (literal);
5608 // if P == '0' && W == '1' then SEE LDRT;
5609 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005610 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5611 t = Bits32 (opcode, 15, 12);
5612 n = Bits32 (opcode, 19, 16);
5613 imm32 = Bits32 (opcode, 11, 0);
5614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005615 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5616 index = BitIsSet (opcode, 24);
5617 add = BitIsSet (opcode, 23);
5618 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005619
5620 // if wback && n == t then UNPREDICTABLE;
5621 if (wback && (n == t))
5622 return false;
5623
5624 break;
5625
5626 default:
5627 return false;
5628 }
5629
5630 addr_t address;
5631 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005632 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005633 if (!success)
5634 return false;
5635
5636 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5637 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005638 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005639 else
5640 offset_addr = base_address - imm32;
5641
5642 // address = if index then offset_addr else R[n];
5643 if (index)
5644 address = offset_addr;
5645 else
5646 address = base_address;
5647
5648 // data = MemU[address,4];
5649
5650 Register base_reg;
5651 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5652
5653 EmulateInstruction::Context context;
5654 context.type = eContextRegisterLoad;
5655 context.SetRegisterPlusOffset (base_reg, address - base_address);
5656
5657 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5658 if (!success)
5659 return false;
5660
5661 // if wback then R[n] = offset_addr;
5662 if (wback)
5663 {
5664 context.type = eContextAdjustBaseRegister;
5665 context.SetAddress (offset_addr);
5666 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5667 return false;
5668 }
5669
5670 // if t == 15 then
5671 if (t == 15)
5672 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005673 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005674 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5675 {
5676 // LoadWritePC (data);
5677 context.type = eContextRegisterLoad;
5678 context.SetRegisterPlusOffset (base_reg, address - base_address);
5679 LoadWritePC (context, data);
5680 }
5681 else
5682 return false;
5683 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005684 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005685 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5686 {
5687 // R[t] = data;
5688 context.type = eContextRegisterLoad;
5689 context.SetRegisterPlusOffset (base_reg, address - base_address);
5690 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5691 return false;
5692 }
5693 // else // Can only apply before ARMv7
5694 else
5695 {
5696 // R[t] = ROR(data, 8*UInt(address<1:0>));
5697 data = ROR (data, Bits32 (address, 1, 0));
5698 context.type = eContextRegisterLoad;
5699 context.SetImmediate (data);
5700 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5701 return false;
5702 }
5703
5704 }
5705 return true;
5706}
5707
Caroline Ticefe479112011-02-18 18:52:37 +00005708// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5709// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5710bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005711EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005712{
5713#if 0
5714 if ConditionPassed() then
5715 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5716 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5717 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5718 address = if index then offset_addr else R[n];
5719 data = MemU[address,4];
5720 if wback then R[n] = offset_addr;
5721 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005722 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5723 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005724 R[t] = data;
5725 else // Can only apply before ARMv7
5726 if CurrentInstrSet() == InstrSet_ARM then
5727 R[t] = ROR(data, 8*UInt(address<1:0>));
5728 else
5729 R[t] = bits(32) UNKNOWN;
5730#endif
5731
5732 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005733
Greg Clayton7bc39082011-03-24 23:53:38 +00005734 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005735 {
5736 const uint32_t addr_byte_size = GetAddressByteSize();
5737
5738 uint32_t t;
5739 uint32_t n;
5740 uint32_t m;
5741 bool index;
5742 bool add;
5743 bool wback;
5744 ARM_ShifterType shift_t;
5745 uint32_t shift_n;
5746
5747 switch (encoding)
5748 {
5749 case eEncodingT1:
5750 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5751 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5752 t = Bits32 (opcode, 2, 0);
5753 n = Bits32 (opcode, 5, 3);
5754 m = Bits32 (opcode, 8, 6);
5755
5756 // index = TRUE; add = TRUE; wback = FALSE;
5757 index = true;
5758 add = true;
5759 wback = false;
5760
5761 // (shift_t, shift_n) = (SRType_LSL, 0);
5762 shift_t = SRType_LSL;
5763 shift_n = 0;
5764
5765 break;
5766
5767 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005768 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005769 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5770 t = Bits32 (opcode, 15, 12);
5771 n = Bits32 (opcode, 19, 16);
5772 m = Bits32 (opcode, 3, 0);
5773
5774 // index = TRUE; add = TRUE; wback = FALSE;
5775 index = true;
5776 add = true;
5777 wback = false;
5778
5779 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5780 shift_t = SRType_LSL;
5781 shift_n = Bits32 (opcode, 5, 4);
5782
5783 // if BadReg(m) then UNPREDICTABLE;
5784 if (BadReg (m))
5785 return false;
5786
5787 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5788 if ((t == 15) && InITBlock() && !LastInITBlock())
5789 return false;
5790
5791 break;
5792
5793 case eEncodingA1:
5794 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005795 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005796 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5797 t = Bits32 (opcode, 15, 12);
5798 n = Bits32 (opcode, 19, 16);
5799 m = Bits32 (opcode, 3, 0);
5800
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005801 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005802 index = BitIsSet (opcode, 24);
5803 add = BitIsSet (opcode, 23);
5804 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5805
5806 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5807 uint32_t type = Bits32 (opcode, 6, 5);
5808 uint32_t imm5 = Bits32 (opcode, 11, 7);
5809 shift_n = DecodeImmShift (type, imm5, shift_t);
5810
5811 // if m == 15 then UNPREDICTABLE;
5812 if (m == 15)
5813 return false;
5814
5815 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5816 if (wback && ((n == 15) || (n == t)))
5817 return false;
5818 }
5819 break;
5820
5821
5822 default:
5823 return false;
5824 }
5825
5826 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5827 if (!success)
5828 return false;
5829
5830 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5831 if (!success)
5832 return false;
5833
5834 addr_t offset_addr;
5835 addr_t address;
5836
5837 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Greg Claytonb3448432011-03-24 21:19:54 +00005838 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005839
5840 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5841 if (add)
5842 offset_addr = Rn + offset;
5843 else
5844 offset_addr = Rn - offset;
5845
5846 // address = if index then offset_addr else R[n];
5847 if (index)
5848 address = offset_addr;
5849 else
5850 address = Rn;
5851
5852 // data = MemU[address,4];
5853 Register base_reg;
5854 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5855
5856 EmulateInstruction::Context context;
5857 context.type = eContextRegisterLoad;
5858 context.SetRegisterPlusOffset (base_reg, address - Rn);
5859
5860 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5861 if (!success)
5862 return false;
5863
5864 // if wback then R[n] = offset_addr;
5865 if (wback)
5866 {
5867 context.type = eContextAdjustBaseRegister;
5868 context.SetAddress (offset_addr);
5869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5870 return false;
5871 }
5872
5873 // if t == 15 then
5874 if (t == 15)
5875 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005876 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005877 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5878 {
5879 context.type = eContextRegisterLoad;
5880 context.SetRegisterPlusOffset (base_reg, address - Rn);
5881 LoadWritePC (context, data);
5882 }
5883 else
5884 return false;
5885 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005886 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005887 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5888 {
5889 // R[t] = data;
5890 context.type = eContextRegisterLoad;
5891 context.SetRegisterPlusOffset (base_reg, address - Rn);
5892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5893 return false;
5894 }
5895 else // Can only apply before ARMv7
5896 {
5897 // if CurrentInstrSet() == InstrSet_ARM then
5898 if (CurrentInstrSet () == eModeARM)
5899 {
5900 // R[t] = ROR(data, 8*UInt(address<1:0>));
5901 data = ROR (data, Bits32 (address, 1, 0));
5902 context.type = eContextRegisterLoad;
5903 context.SetImmediate (data);
5904 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5905 return false;
5906 }
5907 else
5908 {
5909 // R[t] = bits(32) UNKNOWN;
5910 WriteBits32Unknown (t);
5911 }
5912 }
5913 }
5914 return true;
5915}
Caroline Tice21b604b2011-02-18 21:06:04 +00005916
5917// LDRB (immediate, Thumb)
5918bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005919EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005920{
5921#if 0
5922 if ConditionPassed() then
5923 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5924 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5925 address = if index then offset_addr else R[n];
5926 R[t] = ZeroExtend(MemU[address,1], 32);
5927 if wback then R[n] = offset_addr;
5928#endif
5929
5930 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005931
Greg Clayton7bc39082011-03-24 23:53:38 +00005932 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005933 {
5934 uint32_t t;
5935 uint32_t n;
5936 uint32_t imm32;
5937 bool index;
5938 bool add;
5939 bool wback;
5940
5941 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5942 switch (encoding)
5943 {
5944 case eEncodingT1:
5945 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5946 t = Bits32 (opcode, 2, 0);
5947 n = Bits32 (opcode, 5, 3);
5948 imm32 = Bits32 (opcode, 10, 6);
5949
5950 // index = TRUE; add = TRUE; wback = FALSE;
5951 index = true;
5952 add = true;
5953 wback= false;
5954
5955 break;
5956
5957 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005958 // if Rt == '1111' then SEE PLD;
5959 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00005960 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5961 t = Bits32 (opcode, 15, 12);
5962 n = Bits32 (opcode, 19, 16);
5963 imm32 = Bits32 (opcode, 11, 0);
5964
5965 // index = TRUE; add = TRUE; wback = FALSE;
5966 index = true;
5967 add = true;
5968 wback = false;
5969
5970 // if t == 13 then UNPREDICTABLE;
5971 if (t == 13)
5972 return false;
5973
5974 break;
5975
5976 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005977 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
5978 // if Rn == '1111' then SEE LDRB (literal);
5979 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
5980 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00005981 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5982 return false;
5983
5984 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5985 t = Bits32 (opcode, 15, 12);
5986 n = Bits32 (opcode, 19, 16);
5987 imm32 = Bits32 (opcode, 7, 0);
5988
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005989 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00005990 index = BitIsSet (opcode, 10);
5991 add = BitIsSet (opcode, 9);
5992 wback = BitIsSet (opcode, 8);
5993
5994 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5995 if (BadReg (t) || (wback && (n == t)))
5996 return false;
5997
5998 break;
5999
6000 default:
6001 return false;
6002 }
6003
6004 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6005 if (!success)
6006 return false;
6007
6008 addr_t address;
6009 addr_t offset_addr;
6010
6011 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6012 if (add)
6013 offset_addr = Rn + imm32;
6014 else
6015 offset_addr = Rn - imm32;
6016
6017 // address = if index then offset_addr else R[n];
6018 if (index)
6019 address = offset_addr;
6020 else
6021 address = Rn;
6022
6023 // R[t] = ZeroExtend(MemU[address,1], 32);
6024 Register base_reg;
6025 Register data_reg;
6026 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6027 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6028
6029 EmulateInstruction::Context context;
6030 context.type = eContextRegisterLoad;
6031 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6032
6033 uint64_t data = MemURead (context, address, 1, 0, &success);
6034 if (!success)
6035 return false;
6036
6037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6038 return false;
6039
6040 // if wback then R[n] = offset_addr;
6041 if (wback)
6042 {
6043 context.type = eContextAdjustBaseRegister;
6044 context.SetAddress (offset_addr);
6045 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6046 return false;
6047 }
6048 }
6049 return true;
6050}
Caroline Ticef55261f2011-02-18 22:24:22 +00006051
6052// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6053// zero-extends it to form a 32-bit word and writes it to a register.
6054bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006055EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006056{
6057#if 0
6058 if ConditionPassed() then
6059 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6060 base = Align(PC,4);
6061 address = if add then (base + imm32) else (base - imm32);
6062 R[t] = ZeroExtend(MemU[address,1], 32);
6063#endif
6064
6065 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006066
Greg Clayton7bc39082011-03-24 23:53:38 +00006067 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006068 {
6069 uint32_t t;
6070 uint32_t imm32;
6071 bool add;
6072 switch (encoding)
6073 {
6074 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006075 // if Rt == '1111' then SEE PLD;
6076 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006077 t = Bits32 (opcode, 15, 12);
6078 imm32 = Bits32 (opcode, 11, 0);
6079 add = BitIsSet (opcode, 23);
6080
6081 // if t == 13 then UNPREDICTABLE;
6082 if (t == 13)
6083 return false;
6084
6085 break;
6086
6087 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006088 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006089 t = Bits32 (opcode, 15, 12);
6090 imm32 = Bits32 (opcode, 11, 0);
6091 add = BitIsSet (opcode, 23);
6092
6093 // if t == 15 then UNPREDICTABLE;
6094 if (t == 15)
6095 return false;
6096 break;
6097
6098 default:
6099 return false;
6100 }
6101
6102 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006103 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006104 if (!success)
6105 return false;
6106
6107 uint32_t base = AlignPC (pc_val);
6108
6109 addr_t address;
6110 // address = if add then (base + imm32) else (base - imm32);
6111 if (add)
6112 address = base + imm32;
6113 else
6114 address = base - imm32;
6115
6116 // R[t] = ZeroExtend(MemU[address,1], 32);
6117 EmulateInstruction::Context context;
6118 context.type = eContextRelativeBranchImmediate;
6119 context.SetImmediate (address - base);
6120
6121 uint64_t data = MemURead (context, address, 1, 0, &success);
6122 if (!success)
6123 return false;
6124
6125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6126 return false;
6127 }
6128 return true;
6129}
Caroline Tice30fec122011-02-18 23:52:21 +00006130
6131// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6132// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6133// optionally be shifted.
6134bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006135EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006136{
6137#if 0
6138 if ConditionPassed() then
6139 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6140 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6141 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6142 address = if index then offset_addr else R[n];
6143 R[t] = ZeroExtend(MemU[address,1],32);
6144 if wback then R[n] = offset_addr;
6145#endif
6146
6147 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006148
Greg Clayton7bc39082011-03-24 23:53:38 +00006149 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006150 {
6151 uint32_t t;
6152 uint32_t n;
6153 uint32_t m;
6154 bool index;
6155 bool add;
6156 bool wback;
6157 ARM_ShifterType shift_t;
6158 uint32_t shift_n;
6159
6160 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6161 switch (encoding)
6162 {
6163 case eEncodingT1:
6164 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6165 t = Bits32 (opcode, 2, 0);
6166 n = Bits32 (opcode, 5, 3);
6167 m = Bits32 (opcode, 8, 6);
6168
6169 // index = TRUE; add = TRUE; wback = FALSE;
6170 index = true;
6171 add = true;
6172 wback = false;
6173
6174 // (shift_t, shift_n) = (SRType_LSL, 0);
6175 shift_t = SRType_LSL;
6176 shift_n = 0;
6177 break;
6178
6179 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006180 // if Rt == '1111' then SEE PLD;
6181 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006182 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6183 t = Bits32 (opcode, 15, 12);
6184 n = Bits32 (opcode, 19, 16);
6185 m = Bits32 (opcode, 3, 0);
6186
6187 // index = TRUE; add = TRUE; wback = FALSE;
6188 index = true;
6189 add = true;
6190 wback = false;
6191
6192 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6193 shift_t = SRType_LSL;
6194 shift_n = Bits32 (opcode, 5, 4);
6195
6196 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6197 if ((t == 13) || BadReg (m))
6198 return false;
6199 break;
6200
6201 case eEncodingA1:
6202 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006203 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006204 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6205 t = Bits32 (opcode, 15, 12);
6206 n = Bits32 (opcode, 19, 16);
6207 m = Bits32 (opcode, 3, 0);
6208
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006209 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006210 index = BitIsSet (opcode, 24);
6211 add = BitIsSet (opcode, 23);
6212 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6213
6214 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6215 uint32_t type = Bits32 (opcode, 6, 5);
6216 uint32_t imm5 = Bits32 (opcode, 11, 7);
6217 shift_n = DecodeImmShift (type, imm5, shift_t);
6218
6219 // if t == 15 || m == 15 then UNPREDICTABLE;
6220 if ((t == 15) || (m == 15))
6221 return false;
6222
6223 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6224 if (wback && ((n == 15) || (n == t)))
6225 return false;
6226 }
6227 break;
6228
6229 default:
6230 return false;
6231 }
6232
6233 addr_t offset_addr;
6234 addr_t address;
6235
6236 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6237 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6238 if (!success)
6239 return false;
6240
6241 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6242
6243 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6244 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6245 if (!success)
6246 return false;
6247
6248 if (add)
6249 offset_addr = Rn + offset;
6250 else
6251 offset_addr = Rn - offset;
6252
6253 // address = if index then offset_addr else R[n];
6254 if (index)
6255 address = offset_addr;
6256 else
6257 address = Rn;
6258
6259 // R[t] = ZeroExtend(MemU[address,1],32);
6260 Register base_reg;
6261 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6262
6263 EmulateInstruction::Context context;
6264 context.type = eContextRegisterLoad;
6265 context.SetRegisterPlusOffset (base_reg, address - Rn);
6266
6267 uint64_t data = MemURead (context, address, 1, 0, &success);
6268 if (!success)
6269 return false;
6270
6271 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6272 return false;
6273
6274 // if wback then R[n] = offset_addr;
6275 if (wback)
6276 {
6277 context.type = eContextAdjustBaseRegister;
6278 context.SetAddress (offset_addr);
6279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6280 return false;
6281 }
6282 }
6283 return true;
6284}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006285
6286// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6287// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6288// post-indexed, or pre-indexed addressing.
6289bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006290EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006291{
6292#if 0
6293 if ConditionPassed() then
6294 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6295 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6296 address = if index then offset_addr else R[n];
6297 data = MemU[address,2];
6298 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006299 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006300 R[t] = ZeroExtend(data, 32);
6301 else // Can only apply before ARMv7
6302 R[t] = bits(32) UNKNOWN;
6303#endif
6304
6305
6306 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006307
Greg Clayton7bc39082011-03-24 23:53:38 +00006308 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006309 {
6310 uint32_t t;
6311 uint32_t n;
6312 uint32_t imm32;
6313 bool index;
6314 bool add;
6315 bool wback;
6316
6317 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6318 switch (encoding)
6319 {
6320 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006321 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006322 t = Bits32 (opcode, 2, 0);
6323 n = Bits32 (opcode, 5, 3);
6324 imm32 = Bits32 (opcode, 10, 6) << 1;
6325
6326 // index = TRUE; add = TRUE; wback = FALSE;
6327 index = true;
6328 add = true;
6329 wback = false;
6330
6331 break;
6332
6333 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006334 // if Rt == '1111' then SEE "Unallocated memory hints";
6335 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006336 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6337 t = Bits32 (opcode, 15, 12);
6338 n = Bits32 (opcode, 19, 16);
6339 imm32 = Bits32 (opcode, 11, 0);
6340
6341 // index = TRUE; add = TRUE; wback = FALSE;
6342 index = true;
6343 add = true;
6344 wback = false;
6345
6346 // if t == 13 then UNPREDICTABLE;
6347 if (t == 13)
6348 return false;
6349 break;
6350
6351 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006352 // if Rn == '1111' then SEE LDRH (literal);
6353 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6354 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6355 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006356 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6357 return false;
6358
6359 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6360 t = Bits32 (opcode, 15, 12);
6361 n = Bits32 (opcode, 19, 16);
6362 imm32 = Bits32 (opcode, 7, 0);
6363
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006364 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006365 index = BitIsSet (opcode, 10);
6366 add = BitIsSet (opcode, 9);
6367 wback = BitIsSet (opcode, 8);
6368
6369 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6370 if (BadReg (t) || (wback && (n == t)))
6371 return false;
6372 break;
6373
6374 default:
6375 return false;
6376 }
6377
6378 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6379 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6380 if (!success)
6381 return false;
6382
6383 addr_t offset_addr;
6384 addr_t address;
6385
6386 if (add)
6387 offset_addr = Rn + imm32;
6388 else
6389 offset_addr = Rn - imm32;
6390
6391 // address = if index then offset_addr else R[n];
6392 if (index)
6393 address = offset_addr;
6394 else
6395 address = Rn;
6396
6397 // data = MemU[address,2];
6398 Register base_reg;
6399 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6400
6401 EmulateInstruction::Context context;
6402 context.type = eContextRegisterLoad;
6403 context.SetRegisterPlusOffset (base_reg, address - Rn);
6404
6405 uint64_t data = MemURead (context, address, 2, 0, &success);
6406 if (!success)
6407 return false;
6408
6409 // if wback then R[n] = offset_addr;
6410 if (wback)
6411 {
6412 context.type = eContextAdjustBaseRegister;
6413 context.SetAddress (offset_addr);
6414 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6415 return false;
6416 }
6417
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006418 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006419 if (UnalignedSupport () || BitIsClear (address, 0))
6420 {
6421 // R[t] = ZeroExtend(data, 32);
6422 context.type = eContextRegisterLoad;
6423 context.SetRegisterPlusOffset (base_reg, address - Rn);
6424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6425 return false;
6426 }
6427 else // Can only apply before ARMv7
6428 {
6429 // R[t] = bits(32) UNKNOWN;
6430 WriteBits32Unknown (t);
6431 }
6432 }
6433 return true;
6434}
Caroline Ticefe479112011-02-18 18:52:37 +00006435
Caroline Tice952b5382011-02-28 23:15:24 +00006436// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6437// zero-extends it to form a 32-bit word, and writes it to a register.
6438bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006439EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006440{
6441#if 0
6442 if ConditionPassed() then
6443 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6444 base = Align(PC,4);
6445 address = if add then (base + imm32) else (base - imm32);
6446 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006447 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006448 R[t] = ZeroExtend(data, 32);
6449 else // Can only apply before ARMv7
6450 R[t] = bits(32) UNKNOWN;
6451#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006452
Caroline Tice952b5382011-02-28 23:15:24 +00006453 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006454
Greg Clayton7bc39082011-03-24 23:53:38 +00006455 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006456 {
6457 uint32_t t;
6458 uint32_t imm32;
6459 bool add;
6460
6461 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6462 switch (encoding)
6463 {
6464 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006465 // if Rt == '1111' then SEE "Unallocated memory hints";
6466 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006467 t = Bits32 (opcode, 15, 12);
6468 imm32 = Bits32 (opcode, 11, 0);
6469 add = BitIsSet (opcode, 23);
6470
6471 // if t == 13 then UNPREDICTABLE;
6472 if (t == 13)
6473 return false;
6474
6475 break;
6476
6477 case eEncodingA1:
6478 {
6479 uint32_t imm4H = Bits32 (opcode, 11, 8);
6480 uint32_t imm4L = Bits32 (opcode, 3, 0);
6481
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006482 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006483 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006484 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006485 add = BitIsSet (opcode, 23);
6486
6487 // if t == 15 then UNPREDICTABLE;
6488 if (t == 15)
6489 return false;
6490 break;
6491 }
6492
6493 default:
6494 return false;
6495 }
6496
6497 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006498 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006499 if (!success)
6500 return false;
6501
6502 addr_t base = AlignPC (pc_value);
6503 addr_t address;
6504
6505 // address = if add then (base + imm32) else (base - imm32);
6506 if (add)
6507 address = base + imm32;
6508 else
6509 address = base - imm32;
6510
6511 // data = MemU[address,2];
6512 Register base_reg;
6513 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6514
6515 EmulateInstruction::Context context;
6516 context.type = eContextRegisterLoad;
6517 context.SetRegisterPlusOffset (base_reg, address - base);
6518
6519 uint64_t data = MemURead (context, address, 2, 0, &success);
6520 if (!success)
6521 return false;
6522
6523
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006524 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006525 if (UnalignedSupport () || BitIsClear (address, 0))
6526 {
6527 // R[t] = ZeroExtend(data, 32);
6528 context.type = eContextRegisterLoad;
6529 context.SetRegisterPlusOffset (base_reg, address - base);
6530 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6531 return false;
6532
6533 }
6534 else // Can only apply before ARMv7
6535 {
6536 // R[t] = bits(32) UNKNOWN;
6537 WriteBits32Unknown (t);
6538 }
6539 }
6540 return true;
6541}
6542
Caroline Tice0e6bc952011-03-01 18:00:42 +00006543// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6544// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6545// be shifted left by 0, 1, 2, or 3 bits.
6546bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006547EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006548{
6549#if 0
6550 if ConditionPassed() then
6551 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6552 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6553 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6554 address = if index then offset_addr else R[n];
6555 data = MemU[address,2];
6556 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006557 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006558 R[t] = ZeroExtend(data, 32);
6559 else // Can only apply before ARMv7
6560 R[t] = bits(32) UNKNOWN;
6561#endif
6562
6563 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006564
Greg Clayton7bc39082011-03-24 23:53:38 +00006565 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006566 {
6567 uint32_t t;
6568 uint32_t n;
6569 uint32_t m;
6570 bool index;
6571 bool add;
6572 bool wback;
6573 ARM_ShifterType shift_t;
6574 uint32_t shift_n;
6575
6576 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6577 switch (encoding)
6578 {
6579 case eEncodingT1:
6580 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6581 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6582 t = Bits32 (opcode, 2, 0);
6583 n = Bits32 (opcode, 5, 3);
6584 m = Bits32 (opcode, 8, 6);
6585
6586 // index = TRUE; add = TRUE; wback = FALSE;
6587 index = true;
6588 add = true;
6589 wback = false;
6590
6591 // (shift_t, shift_n) = (SRType_LSL, 0);
6592 shift_t = SRType_LSL;
6593 shift_n = 0;
6594
6595 break;
6596
6597 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006598 // if Rn == '1111' then SEE LDRH (literal);
6599 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006600 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6601 t = Bits32 (opcode, 15, 12);
6602 n = Bits32 (opcode, 19, 16);
6603 m = Bits32 (opcode, 3, 0);
6604
6605 // index = TRUE; add = TRUE; wback = FALSE;
6606 index = true;
6607 add = true;
6608 wback = false;
6609
6610 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6611 shift_t = SRType_LSL;
6612 shift_n = Bits32 (opcode, 5, 4);
6613
6614 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6615 if ((t == 13) || BadReg (m))
6616 return false;
6617 break;
6618
6619 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006620 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006621 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6622 t = Bits32 (opcode, 15, 12);
6623 n = Bits32 (opcode, 19, 16);
6624 m = Bits32 (opcode, 3, 0);
6625
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006626 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006627 index = BitIsSet (opcode, 24);
6628 add = BitIsSet (opcode, 23);
6629 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6630
6631 // (shift_t, shift_n) = (SRType_LSL, 0);
6632 shift_t = SRType_LSL;
6633 shift_n = 0;
6634
6635 // if t == 15 || m == 15 then UNPREDICTABLE;
6636 if ((t == 15) || (m == 15))
6637 return false;
6638
6639 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6640 if (wback && ((n == 15) || (n == t)))
6641 return false;
6642
6643 break;
6644
6645 default:
6646 return false;
6647 }
6648
6649 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6650
6651 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6652 if (!success)
6653 return false;
6654
6655 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6656
6657 addr_t offset_addr;
6658 addr_t address;
6659
6660 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6661 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6662 if (!success)
6663 return false;
6664
6665 if (add)
6666 offset_addr = Rn + offset;
6667 else
6668 offset_addr = Rn - offset;
6669
6670 // address = if index then offset_addr else R[n];
6671 if (index)
6672 address = offset_addr;
6673 else
6674 address = Rn;
6675
6676 // data = MemU[address,2];
6677 Register base_reg;
6678 Register offset_reg;
6679 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6680 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6681
6682 EmulateInstruction::Context context;
6683 context.type = eContextRegisterLoad;
6684 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6685 uint64_t data = MemURead (context, address, 2, 0, &success);
6686 if (!success)
6687 return false;
6688
6689 // if wback then R[n] = offset_addr;
6690 if (wback)
6691 {
6692 context.type = eContextAdjustBaseRegister;
6693 context.SetAddress (offset_addr);
6694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6695 return false;
6696 }
6697
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006698 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006699 if (UnalignedSupport() || BitIsClear (address, 0))
6700 {
6701 // R[t] = ZeroExtend(data, 32);
6702 context.type = eContextRegisterLoad;
6703 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6704 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6705 return false;
6706 }
6707 else // Can only apply before ARMv7
6708 {
6709 // R[t] = bits(32) UNKNOWN;
6710 WriteBits32Unknown (t);
6711 }
6712 }
6713 return true;
6714}
6715
Caroline Ticea5e28af2011-03-01 21:53:03 +00006716// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6717// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6718// or pre-indexed addressing.
6719bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006720EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006721{
6722#if 0
6723 if ConditionPassed() then
6724 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6726 address = if index then offset_addr else R[n];
6727 R[t] = SignExtend(MemU[address,1], 32);
6728 if wback then R[n] = offset_addr;
6729#endif
6730
6731 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006732
Greg Clayton7bc39082011-03-24 23:53:38 +00006733 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006734 {
6735 uint32_t t;
6736 uint32_t n;
6737 uint32_t imm32;
6738 bool index;
6739 bool add;
6740 bool wback;
6741
6742 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6743 switch (encoding)
6744 {
6745 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006746 // if Rt == '1111' then SEE PLI;
6747 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006748 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6749 t = Bits32 (opcode, 15, 12);
6750 n = Bits32 (opcode, 19, 16);
6751 imm32 = Bits32 (opcode, 11, 0);
6752
6753 // index = TRUE; add = TRUE; wback = FALSE;
6754 index = true;
6755 add = true;
6756 wback = false;
6757
6758 // if t == 13 then UNPREDICTABLE;
6759 if (t == 13)
6760 return false;
6761
6762 break;
6763
6764 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006765 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6766 // if Rn == '1111' then SEE LDRSB (literal);
6767 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6768 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006769 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6770 return false;
6771
6772 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6773 t = Bits32 (opcode, 15, 12);
6774 n = Bits32 (opcode, 19, 16);
6775 imm32 = Bits32 (opcode, 7, 0);
6776
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006777 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006778 index = BitIsSet (opcode, 10);
6779 add = BitIsSet (opcode, 9);
6780 wback = BitIsSet (opcode, 8);
6781
6782 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006783 if (((t == 13) || ((t == 15)
6784 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6785 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006786 return false;
6787
6788 break;
6789
6790 case eEncodingA1:
6791 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006792 // if Rn == '1111' then SEE LDRSB (literal);
6793 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006794 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6795 t = Bits32 (opcode, 15, 12);
6796 n = Bits32 (opcode, 19, 16);
6797
6798 uint32_t imm4H = Bits32 (opcode, 11, 8);
6799 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006800 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006801
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006802 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006803 index = BitIsSet (opcode, 24);
6804 add = BitIsSet (opcode, 23);
6805 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6806
6807 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6808 if ((t == 15) || (wback && (n == t)))
6809 return false;
6810
6811 break;
6812 }
6813
6814 default:
6815 return false;
6816 }
6817
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006818 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006819 if (!success)
6820 return false;
6821
6822 addr_t offset_addr;
6823 addr_t address;
6824
6825 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6826 if (add)
6827 offset_addr = Rn + imm32;
6828 else
6829 offset_addr = Rn - imm32;
6830
6831 // address = if index then offset_addr else R[n];
6832 if (index)
6833 address = offset_addr;
6834 else
6835 address = Rn;
6836
6837 // R[t] = SignExtend(MemU[address,1], 32);
6838 Register base_reg;
6839 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6840
6841 EmulateInstruction::Context context;
6842 context.type = eContextRegisterLoad;
6843 context.SetRegisterPlusOffset (base_reg, address - Rn);
6844
6845 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6846 if (!success)
6847 return false;
6848
6849 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6851 return false;
6852
6853 // if wback then R[n] = offset_addr;
6854 if (wback)
6855 {
6856 context.type = eContextAdjustBaseRegister;
6857 context.SetAddress (offset_addr);
6858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6859 return false;
6860 }
6861 }
6862
6863 return true;
6864}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006865
Caroline Tice5f593912011-03-01 22:25:17 +00006866// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6867// sign-extends it to form a 32-bit word, and writes tit to a register.
6868bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006869EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006870{
6871#if 0
6872 if ConditionPassed() then
6873 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6874 base = Align(PC,4);
6875 address = if add then (base + imm32) else (base - imm32);
6876 R[t] = SignExtend(MemU[address,1], 32);
6877#endif
6878
6879 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006880
Greg Clayton7bc39082011-03-24 23:53:38 +00006881 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006882 {
6883 uint32_t t;
6884 uint32_t imm32;
6885 bool add;
6886
6887 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6888 switch (encoding)
6889 {
6890 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006891 // if Rt == '1111' then SEE PLI;
6892 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006893 t = Bits32 (opcode, 15, 12);
6894 imm32 = Bits32 (opcode, 11, 0);
6895 add = BitIsSet (opcode, 23);
6896
6897 // if t == 13 then UNPREDICTABLE;
6898 if (t == 13)
6899 return false;
6900
6901 break;
6902
6903 case eEncodingA1:
6904 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006905 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006906 t = Bits32 (opcode, 15, 12);
6907 uint32_t imm4H = Bits32 (opcode, 11, 8);
6908 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006909 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006910 add = BitIsSet (opcode, 23);
6911
6912 // if t == 15 then UNPREDICTABLE;
6913 if (t == 15)
6914 return false;
6915
6916 break;
6917 }
6918
6919 default:
6920 return false;
6921 }
6922
6923 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006924 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006925 if (!success)
6926 return false;
6927 uint64_t base = AlignPC (pc_value);
6928
6929 // address = if add then (base + imm32) else (base - imm32);
6930 addr_t address;
6931 if (add)
6932 address = base + imm32;
6933 else
6934 address = base - imm32;
6935
6936 // R[t] = SignExtend(MemU[address,1], 32);
6937 Register base_reg;
6938 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6939
6940 EmulateInstruction::Context context;
6941 context.type = eContextRegisterLoad;
6942 context.SetRegisterPlusOffset (base_reg, address - base);
6943
6944 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6945 if (!success)
6946 return false;
6947
6948 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6950 return false;
6951 }
6952 return true;
6953}
6954
Caroline Tice672f3112011-03-01 23:55:59 +00006955// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6956// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6957// shifted left by 0, 1, 2, or 3 bits.
6958bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006959EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00006960{
6961#if 0
6962 if ConditionPassed() then
6963 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6964 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6965 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6966 address = if index then offset_addr else R[n];
6967 R[t] = SignExtend(MemU[address,1], 32);
6968 if wback then R[n] = offset_addr;
6969#endif
6970
6971 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00006972
Greg Clayton7bc39082011-03-24 23:53:38 +00006973 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00006974 {
6975 uint32_t t;
6976 uint32_t n;
6977 uint32_t m;
6978 bool index;
6979 bool add;
6980 bool wback;
6981 ARM_ShifterType shift_t;
6982 uint32_t shift_n;
6983
6984 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6985 switch (encoding)
6986 {
6987 case eEncodingT1:
6988 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6989 t = Bits32 (opcode, 2, 0);
6990 n = Bits32 (opcode, 5, 3);
6991 m = Bits32 (opcode, 8, 6);
6992
6993 // index = TRUE; add = TRUE; wback = FALSE;
6994 index = true;
6995 add = true;
6996 wback = false;
6997
6998 // (shift_t, shift_n) = (SRType_LSL, 0);
6999 shift_t = SRType_LSL;
7000 shift_n = 0;
7001
7002 break;
7003
7004 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007005 // if Rt == '1111' then SEE PLI;
7006 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007007 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7008 t = Bits32 (opcode, 15, 12);
7009 n = Bits32 (opcode, 19, 16);
7010 m = Bits32 (opcode, 3, 0);
7011
7012 // index = TRUE; add = TRUE; wback = FALSE;
7013 index = true;
7014 add = true;
7015 wback = false;
7016
7017 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7018 shift_t = SRType_LSL;
7019 shift_n = Bits32 (opcode, 5, 4);
7020
7021 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7022 if ((t == 13) || BadReg (m))
7023 return false;
7024 break;
7025
7026 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007027 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007028 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7029 t = Bits32 (opcode, 15, 12);
7030 n = Bits32 (opcode, 19, 16);
7031 m = Bits32 (opcode, 3, 0);
7032
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007033 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007034 index = BitIsSet (opcode, 24);
7035 add = BitIsSet (opcode, 23);
7036 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7037
7038 // (shift_t, shift_n) = (SRType_LSL, 0);
7039 shift_t = SRType_LSL;
7040 shift_n = 0;
7041
7042 // if t == 15 || m == 15 then UNPREDICTABLE;
7043 if ((t == 15) || (m == 15))
7044 return false;
7045
7046 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7047 if (wback && ((n == 15) || (n == t)))
7048 return false;
7049 break;
7050
7051 default:
7052 return false;
7053 }
7054
7055 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7056 if (!success)
7057 return false;
7058
7059 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7060 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7061
7062 addr_t offset_addr;
7063 addr_t address;
7064
7065 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7066 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7067 if (!success)
7068 return false;
7069
7070 if (add)
7071 offset_addr = Rn + offset;
7072 else
7073 offset_addr = Rn - offset;
7074
7075 // address = if index then offset_addr else R[n];
7076 if (index)
7077 address = offset_addr;
7078 else
7079 address = Rn;
7080
7081 // R[t] = SignExtend(MemU[address,1], 32);
7082 Register base_reg;
7083 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7084 Register offset_reg;
7085 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7086
7087 EmulateInstruction::Context context;
7088 context.type = eContextRegisterLoad;
7089 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7090
7091 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7092 if (!success)
7093 return false;
7094
7095 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7096 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7097 return false;
7098
7099 // if wback then R[n] = offset_addr;
7100 if (wback)
7101 {
7102 context.type = eContextAdjustBaseRegister;
7103 context.SetAddress (offset_addr);
7104 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7105 return false;
7106 }
7107 }
7108 return true;
7109}
7110
Caroline Tice78fb5632011-03-02 00:39:42 +00007111// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7112// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7113// pre-indexed addressing.
7114bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007115EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007116{
7117#if 0
7118 if ConditionPassed() then
7119 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7120 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7121 address = if index then offset_addr else R[n];
7122 data = MemU[address,2];
7123 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007124 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007125 R[t] = SignExtend(data, 32);
7126 else // Can only apply before ARMv7
7127 R[t] = bits(32) UNKNOWN;
7128#endif
7129
7130 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007131
Greg Clayton7bc39082011-03-24 23:53:38 +00007132 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007133 {
7134 uint32_t t;
7135 uint32_t n;
7136 uint32_t imm32;
7137 bool index;
7138 bool add;
7139 bool wback;
7140
7141 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7142 switch (encoding)
7143 {
7144 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007145 // if Rn == '1111' then SEE LDRSH (literal);
7146 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007147 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7148 t = Bits32 (opcode, 15, 12);
7149 n = Bits32 (opcode, 19, 16);
7150 imm32 = Bits32 (opcode, 11, 0);
7151
7152 // index = TRUE; add = TRUE; wback = FALSE;
7153 index = true;
7154 add = true;
7155 wback = false;
7156
7157 // if t == 13 then UNPREDICTABLE;
7158 if (t == 13)
7159 return false;
7160
7161 break;
7162
7163 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007164 // if Rn == '1111' then SEE LDRSH (literal);
7165 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7166 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7167 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007168 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7169 return false;
7170
7171 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7172 t = Bits32 (opcode, 15, 12);
7173 n = Bits32 (opcode, 19, 16);
7174 imm32 = Bits32 (opcode, 7, 0);
7175
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007176 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007177 index = BitIsSet (opcode, 10);
7178 add = BitIsSet (opcode, 9);
7179 wback = BitIsSet (opcode, 8);
7180
7181 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7182 if (BadReg (t) || (wback && (n == t)))
7183 return false;
7184
7185 break;
7186
7187 case eEncodingA1:
7188 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007189 // if Rn == '1111' then SEE LDRSH (literal);
7190 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007191 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7192 t = Bits32 (opcode, 15, 12);
7193 n = Bits32 (opcode, 19, 16);
7194 uint32_t imm4H = Bits32 (opcode, 11,8);
7195 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007196 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007197
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007198 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007199 index = BitIsSet (opcode, 24);
7200 add = BitIsSet (opcode, 23);
7201 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7202
7203 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7204 if ((t == 15) || (wback && (n == t)))
7205 return false;
7206
7207 break;
7208 }
7209
7210 default:
7211 return false;
7212 }
7213
7214 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7215 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7216 if (!success)
7217 return false;
7218
7219 addr_t offset_addr;
7220 if (add)
7221 offset_addr = Rn + imm32;
7222 else
7223 offset_addr = Rn - imm32;
7224
7225 // address = if index then offset_addr else R[n];
7226 addr_t address;
7227 if (index)
7228 address = offset_addr;
7229 else
7230 address = Rn;
7231
7232 // data = MemU[address,2];
7233 Register base_reg;
7234 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7235
7236 EmulateInstruction::Context context;
7237 context.type = eContextRegisterLoad;
7238 context.SetRegisterPlusOffset (base_reg, address - Rn);
7239
7240 uint64_t data = MemURead (context, address, 2, 0, &success);
7241 if (!success)
7242 return false;
7243
7244 // if wback then R[n] = offset_addr;
7245 if (wback)
7246 {
7247 context.type = eContextAdjustBaseRegister;
7248 context.SetAddress (offset_addr);
7249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7250 return false;
7251 }
7252
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007253 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007254 if (UnalignedSupport() || BitIsClear (address, 0))
7255 {
7256 // R[t] = SignExtend(data, 32);
7257 int64_t signed_data = llvm::SignExtend64<16>(data);
7258 context.type = eContextRegisterLoad;
7259 context.SetRegisterPlusOffset (base_reg, address - Rn);
7260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7261 return false;
7262 }
7263 else // Can only apply before ARMv7
7264 {
7265 // R[t] = bits(32) UNKNOWN;
7266 WriteBits32Unknown (t);
7267 }
7268 }
7269 return true;
7270}
7271
Caroline Ticed2fac092011-03-02 19:45:34 +00007272// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7273// sign-extends it to from a 32-bit word, and writes it to a register.
7274bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007275EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007276{
7277#if 0
7278 if ConditionPassed() then
7279 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7280 base = Align(PC,4);
7281 address = if add then (base + imm32) else (base - imm32);
7282 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007283 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007284 R[t] = SignExtend(data, 32);
7285 else // Can only apply before ARMv7
7286 R[t] = bits(32) UNKNOWN;
7287#endif
7288
7289 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007290
Greg Clayton7bc39082011-03-24 23:53:38 +00007291 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007292 {
7293 uint32_t t;
7294 uint32_t imm32;
7295 bool add;
7296
7297 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7298 switch (encoding)
7299 {
7300 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007301 // if Rt == '1111' then SEE "Unallocated memory hints";
7302 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007303 t = Bits32 (opcode, 15, 12);
7304 imm32 = Bits32 (opcode, 11, 0);
7305 add = BitIsSet (opcode, 23);
7306
7307 // if t == 13 then UNPREDICTABLE;
7308 if (t == 13)
7309 return false;
7310
7311 break;
7312
7313 case eEncodingA1:
7314 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007315 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007316 t = Bits32 (opcode, 15, 12);
7317 uint32_t imm4H = Bits32 (opcode, 11, 8);
7318 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007319 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007320 add = BitIsSet (opcode, 23);
7321
7322 // if t == 15 then UNPREDICTABLE;
7323 if (t == 15)
7324 return false;
7325
7326 break;
7327 }
7328 default:
7329 return false;
7330 }
7331
7332 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007333 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007334 if (!success)
7335 return false;
7336
7337 uint64_t base = AlignPC (pc_value);
7338
7339 addr_t address;
7340 // address = if add then (base + imm32) else (base - imm32);
7341 if (add)
7342 address = base + imm32;
7343 else
7344 address = base - imm32;
7345
7346 // data = MemU[address,2];
7347 Register base_reg;
7348 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7349
7350 EmulateInstruction::Context context;
7351 context.type = eContextRegisterLoad;
7352 context.SetRegisterPlusOffset (base_reg, imm32);
7353
7354 uint64_t data = MemURead (context, address, 2, 0, &success);
7355 if (!success)
7356 return false;
7357
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007358 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007359 if (UnalignedSupport() || BitIsClear (address, 0))
7360 {
7361 // R[t] = SignExtend(data, 32);
7362 int64_t signed_data = llvm::SignExtend64<16>(data);
7363 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7364 return false;
7365 }
7366 else // Can only apply before ARMv7
7367 {
7368 // R[t] = bits(32) UNKNOWN;
7369 WriteBits32Unknown (t);
7370 }
7371 }
7372 return true;
7373}
7374
Caroline Tice291a3e92011-03-02 21:13:44 +00007375// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7376// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7377// shifted left by 0, 1, 2, or 3 bits.
7378bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007379EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007380{
7381#if 0
7382 if ConditionPassed() then
7383 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7384 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7385 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7386 address = if index then offset_addr else R[n];
7387 data = MemU[address,2];
7388 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007389 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007390 R[t] = SignExtend(data, 32);
7391 else // Can only apply before ARMv7
7392 R[t] = bits(32) UNKNOWN;
7393#endif
7394
7395 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007396
Greg Clayton7bc39082011-03-24 23:53:38 +00007397 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007398 {
7399 uint32_t t;
7400 uint32_t n;
7401 uint32_t m;
7402 bool index;
7403 bool add;
7404 bool wback;
7405 ARM_ShifterType shift_t;
7406 uint32_t shift_n;
7407
7408 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7409 switch (encoding)
7410 {
7411 case eEncodingT1:
7412 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7413 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7414 t = Bits32 (opcode, 2, 0);
7415 n = Bits32 (opcode, 5, 3);
7416 m = Bits32 (opcode, 8, 6);
7417
7418 // index = TRUE; add = TRUE; wback = FALSE;
7419 index = true;
7420 add = true;
7421 wback = false;
7422
7423 // (shift_t, shift_n) = (SRType_LSL, 0);
7424 shift_t = SRType_LSL;
7425 shift_n = 0;
7426
7427 break;
7428
7429 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007430 // if Rn == '1111' then SEE LDRSH (literal);
7431 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007432 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7433 t = Bits32 (opcode, 15, 12);
7434 n = Bits32 (opcode, 19, 16);
7435 m = Bits32 (opcode, 3, 0);
7436
7437 // index = TRUE; add = TRUE; wback = FALSE;
7438 index = true;
7439 add = true;
7440 wback = false;
7441
7442 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7443 shift_t = SRType_LSL;
7444 shift_n = Bits32 (opcode, 5, 4);
7445
7446 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7447 if ((t == 13) || BadReg (m))
7448 return false;
7449
7450 break;
7451
7452 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007453 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007454 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7455 t = Bits32 (opcode, 15, 12);
7456 n = Bits32 (opcode, 19, 16);
7457 m = Bits32 (opcode, 3, 0);
7458
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007459 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007460 index = BitIsSet (opcode, 24);
7461 add = BitIsSet (opcode, 23);
7462 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7463
7464 // (shift_t, shift_n) = (SRType_LSL, 0);
7465 shift_t = SRType_LSL;
7466 shift_n = 0;
7467
7468 // if t == 15 || m == 15 then UNPREDICTABLE;
7469 if ((t == 15) || (m == 15))
7470 return false;
7471
7472 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7473 if (wback && ((n == 15) || (n == t)))
7474 return false;
7475
7476 break;
7477
7478 default:
7479 break;
7480 }
7481
7482 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7483 if (!success)
7484 return false;
7485
7486 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7487 if (!success)
7488 return false;
7489
7490 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7491 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7492
7493 addr_t offset_addr;
7494 addr_t address;
7495
7496 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7497 if (add)
7498 offset_addr = Rn + offset;
7499 else
7500 offset_addr = Rn - offset;
7501
7502 // address = if index then offset_addr else R[n];
7503 if (index)
7504 address = offset_addr;
7505 else
7506 address = Rn;
7507
7508 // data = MemU[address,2];
7509 Register base_reg;
7510 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7511
7512 Register offset_reg;
7513 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7514
7515 EmulateInstruction::Context context;
7516 context.type = eContextRegisterLoad;
7517 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7518
7519 uint64_t data = MemURead (context, address, 2, 0, &success);
7520 if (!success)
7521 return false;
7522
7523 // if wback then R[n] = offset_addr;
7524 if (wback)
7525 {
7526 context.type = eContextAdjustBaseRegister;
7527 context.SetAddress (offset_addr);
7528 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7529 return false;
7530 }
7531
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007532 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007533 if (UnalignedSupport() || BitIsClear (address, 0))
7534 {
7535 // R[t] = SignExtend(data, 32);
7536 context.type = eContextRegisterLoad;
7537 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7538
7539 int64_t signed_data = llvm::SignExtend64<16>(data);
7540 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7541 return false;
7542 }
7543 else // Can only apply before ARMv7
7544 {
7545 // R[t] = bits(32) UNKNOWN;
7546 WriteBits32Unknown (t);
7547 }
7548 }
7549 return true;
7550}
Caroline Tice6bf65162011-03-03 17:42:58 +00007551
7552// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7553// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7554bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007555EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007556{
7557#if 0
7558 if ConditionPassed() then
7559 EncodingSpecificOperations();
7560 rotated = ROR(R[m], rotation);
7561 R[d] = SignExtend(rotated<7:0>, 32);
7562#endif
7563
7564 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007565
Greg Clayton7bc39082011-03-24 23:53:38 +00007566 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007567 {
7568 uint32_t d;
7569 uint32_t m;
7570 uint32_t rotation;
7571
7572 // EncodingSpecificOperations();
7573 switch (encoding)
7574 {
7575 case eEncodingT1:
7576 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7577 d = Bits32 (opcode, 2, 0);
7578 m = Bits32 (opcode, 5, 3);
7579 rotation = 0;
7580
7581 break;
7582
7583 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007584 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007585 d = Bits32 (opcode, 11, 8);
7586 m = Bits32 (opcode, 3, 0);
7587 rotation = Bits32 (opcode, 5, 4) << 3;
7588
7589 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7590 if (BadReg (d) || BadReg (m))
7591 return false;
7592
7593 break;
7594
7595 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007596 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007597 d = Bits32 (opcode, 15, 12);
7598 m = Bits32 (opcode, 3, 0);
7599 rotation = Bits32 (opcode, 11, 10) << 3;
7600
7601 // if d == 15 || m == 15 then UNPREDICTABLE;
7602 if ((d == 15) || (m == 15))
7603 return false;
7604
7605 break;
7606
7607 default:
7608 return false;
7609 }
7610
Caroline Tice868198b2011-03-03 18:04:49 +00007611 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7612 if (!success)
7613 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007614
7615 // rotated = ROR(R[m], rotation);
7616 uint64_t rotated = ROR (Rm, rotation);
7617
7618 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007619 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007620
7621 Register source_reg;
7622 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7623
7624 EmulateInstruction::Context context;
7625 context.type = eContextRegisterLoad;
7626 context.SetRegister (source_reg);
7627
Caroline Tice8ce96d92011-03-03 18:27:17 +00007628 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007629 return false;
7630 }
7631 return true;
7632}
Caroline Tice291a3e92011-03-02 21:13:44 +00007633
Caroline Tice868198b2011-03-03 18:04:49 +00007634// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7635// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7636bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007637EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007638{
7639#if 0
7640 if ConditionPassed() then
7641 EncodingSpecificOperations();
7642 rotated = ROR(R[m], rotation);
7643 R[d] = SignExtend(rotated<15:0>, 32);
7644#endif
7645
7646 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007647
Greg Clayton7bc39082011-03-24 23:53:38 +00007648 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007649 {
7650 uint32_t d;
7651 uint32_t m;
7652 uint32_t rotation;
7653
7654 // EncodingSpecificOperations();
7655 switch (encoding)
7656 {
7657 case eEncodingT1:
7658 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7659 d = Bits32 (opcode, 2, 0);
7660 m = Bits32 (opcode, 5, 3);
7661 rotation = 0;
7662
7663 break;
7664
7665 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007666 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007667 d = Bits32 (opcode, 11, 8);
7668 m = Bits32 (opcode, 3, 0);
7669 rotation = Bits32 (opcode, 5, 4) << 3;
7670
7671 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7672 if (BadReg (d) || BadReg (m))
7673 return false;
7674
7675 break;
7676
7677 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007678 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007679 d = Bits32 (opcode, 15, 12);
7680 m = Bits32 (opcode, 3, 0);
7681 rotation = Bits32 (opcode, 11, 10) << 3;
7682
7683 // if d == 15 || m == 15 then UNPREDICTABLE;
7684 if ((d == 15) || (m == 15))
7685 return false;
7686
7687 break;
7688
7689 default:
7690 return false;
7691 }
7692
7693 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7694 if (!success)
7695 return false;
7696
7697 // rotated = ROR(R[m], rotation);
7698 uint64_t rotated = ROR (Rm, rotation);
7699
7700 // R[d] = SignExtend(rotated<15:0>, 32);
7701 Register source_reg;
7702 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7703
7704 EmulateInstruction::Context context;
7705 context.type = eContextRegisterLoad;
7706 context.SetRegister (source_reg);
7707
Caroline Tice8ce96d92011-03-03 18:27:17 +00007708 int64_t data = llvm::SignExtend64<16> (rotated);
7709 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007710 return false;
7711 }
7712
7713 return true;
7714}
7715
Caroline Tice8ce96d92011-03-03 18:27:17 +00007716// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7717// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7718bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007719EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007720{
7721#if 0
7722 if ConditionPassed() then
7723 EncodingSpecificOperations();
7724 rotated = ROR(R[m], rotation);
7725 R[d] = ZeroExtend(rotated<7:0>, 32);
7726#endif
7727
7728 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007729
Greg Clayton7bc39082011-03-24 23:53:38 +00007730 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007731 {
7732 uint32_t d;
7733 uint32_t m;
7734 uint32_t rotation;
7735
7736 // EncodingSpecificOperations();
7737 switch (encoding)
7738 {
7739 case eEncodingT1:
7740 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7741 d = Bits32 (opcode, 2, 0);
7742 m = Bits32 (opcode, 5, 3);
7743 rotation = 0;
7744
7745 break;
7746
7747 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007748 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007749 d = Bits32 (opcode, 11, 8);
7750 m = Bits32 (opcode, 3, 0);
7751 rotation = Bits32 (opcode, 5, 4) << 3;
7752
7753 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7754 if (BadReg (d) || BadReg (m))
7755 return false;
7756
7757 break;
7758
7759 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007760 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007761 d = Bits32 (opcode, 15, 12);
7762 m = Bits32 (opcode, 3, 0);
7763 rotation = Bits32 (opcode, 11, 10) << 3;
7764
7765 // if d == 15 || m == 15 then UNPREDICTABLE;
7766 if ((d == 15) || (m == 15))
7767 return false;
7768
7769 break;
7770
7771 default:
7772 return false;
7773 }
7774
7775 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7776 if (!success)
7777 return false;
7778
7779 // rotated = ROR(R[m], rotation);
7780 uint64_t rotated = ROR (Rm, rotation);
7781
7782 // R[d] = ZeroExtend(rotated<7:0>, 32);
7783 Register source_reg;
7784 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7785
7786 EmulateInstruction::Context context;
7787 context.type = eContextRegisterLoad;
7788 context.SetRegister (source_reg);
7789
7790 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7791 return false;
7792 }
7793 return true;
7794}
7795
Caroline Tice11555f22011-03-03 18:48:58 +00007796// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7797// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7798bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007799EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007800{
7801#if 0
7802 if ConditionPassed() then
7803 EncodingSpecificOperations();
7804 rotated = ROR(R[m], rotation);
7805 R[d] = ZeroExtend(rotated<15:0>, 32);
7806#endif
7807
7808 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007809
Greg Clayton7bc39082011-03-24 23:53:38 +00007810 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007811 {
7812 uint32_t d;
7813 uint32_t m;
7814 uint32_t rotation;
7815
7816 switch (encoding)
7817 {
7818 case eEncodingT1:
7819 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7820 d = Bits32 (opcode, 2, 0);
7821 m = Bits32 (opcode, 5, 3);
7822 rotation = 0;
7823
7824 break;
7825
7826 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007827 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007828 d = Bits32 (opcode, 11, 8);
7829 m = Bits32 (opcode, 3, 0);
7830 rotation = Bits32 (opcode, 5, 4) << 3;
7831
7832 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7833 if (BadReg (d) || BadReg (m))
7834 return false;
7835
7836 break;
7837
7838 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007839 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007840 d = Bits32 (opcode, 15, 12);
7841 m = Bits32 (opcode, 3, 0);
7842 rotation = Bits32 (opcode, 11, 10) << 3;
7843
7844 // if d == 15 || m == 15 then UNPREDICTABLE;
7845 if ((d == 15) || (m == 15))
7846 return false;
7847
7848 break;
7849
7850 default:
7851 return false;
7852 }
7853
7854 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7855 if (!success)
7856 return false;
7857
7858 // rotated = ROR(R[m], rotation);
7859 uint64_t rotated = ROR (Rm, rotation);
7860
7861 // R[d] = ZeroExtend(rotated<15:0>, 32);
7862 Register source_reg;
7863 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7864
7865 EmulateInstruction::Context context;
7866 context.type = eContextRegisterLoad;
7867 context.SetRegister (source_reg);
7868
7869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7870 return false;
7871 }
7872 return true;
7873}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007874
7875// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7876// word respectively.
7877bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007878EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007879{
7880#if 0
7881 if ConditionPassed() then
7882 EncodingSpecificOperations();
7883 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7884 UNPREDICTABLE;
7885 else
7886 address = if increment then R[n] else R[n]-8;
7887 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007888 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007889 BranchWritePC(MemA[address,4]);
7890 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7891#endif
7892
7893 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007894
Greg Clayton7bc39082011-03-24 23:53:38 +00007895 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007896 {
7897 uint32_t n;
7898 bool wback;
7899 bool increment;
7900 bool wordhigher;
7901
7902 // EncodingSpecificOperations();
7903 switch (encoding)
7904 {
7905 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007906 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007907 n = Bits32 (opcode, 19, 16);
7908 wback = BitIsSet (opcode, 21);
7909 increment = false;
7910 wordhigher = false;
7911
7912 // if n == 15 then UNPREDICTABLE;
7913 if (n == 15)
7914 return false;
7915
7916 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7917 if (InITBlock() && !LastInITBlock())
7918 return false;
7919
7920 break;
7921
7922 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007923 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007924 n = Bits32 (opcode, 19, 16);
7925 wback = BitIsSet (opcode, 21);
7926 increment = true;
7927 wordhigher = false;
7928
7929 // if n == 15 then UNPREDICTABLE;
7930 if (n == 15)
7931 return false;
7932
7933 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7934 if (InITBlock() && !LastInITBlock())
7935 return false;
7936
7937 break;
7938
7939 case eEncodingA1:
7940 // n = UInt(Rn);
7941 n = Bits32 (opcode, 19, 16);
7942
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007943 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007944 wback = BitIsSet (opcode, 21);
7945 increment = BitIsSet (opcode, 23);
7946 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7947
7948 // if n == 15 then UNPREDICTABLE;
7949 if (n == 15)
7950 return false;
7951
7952 break;
7953
7954 default:
7955 return false;
7956 }
7957
7958 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7959 if (!CurrentModeIsPrivileged ())
7960 // UNPREDICTABLE;
7961 return false;
7962 else
7963 {
7964 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7965 if (!success)
7966 return false;
7967
7968 addr_t address;
7969 // address = if increment then R[n] else R[n]-8;
7970 if (increment)
7971 address = Rn;
7972 else
7973 address = Rn - 8;
7974
7975 // if wordhigher then address = address+4;
7976 if (wordhigher)
7977 address = address + 4;
7978
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007979 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007980 Register base_reg;
7981 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7982
7983 EmulateInstruction::Context context;
7984 context.type = eContextReturnFromException;
7985 context.SetRegisterPlusOffset (base_reg, address - Rn);
7986
7987 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7988 if (!success)
7989 return false;
7990
7991 CPSRWriteByInstr (data, 15, true);
7992
7993 // BranchWritePC(MemA[address,4]);
7994 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7995 if (!success)
7996 return false;
7997
7998 BranchWritePC (context, data2);
7999
8000 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8001 if (wback)
8002 {
8003 context.type = eContextAdjustBaseRegister;
8004 if (increment)
8005 {
8006 context.SetOffset (8);
8007 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8008 return false;
8009 }
8010 else
8011 {
8012 context.SetOffset (-8);
8013 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8014 return false;
8015 }
8016 } // if wback
8017 }
8018 } // if ConditionPassed()
8019 return true;
8020}
Caroline Tice11555f22011-03-03 18:48:58 +00008021
Johnny Chen2115b412011-02-21 23:42:44 +00008022// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8023// and writes the result to the destination register. It can optionally update the condition flags based on
8024// the result.
8025bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008026EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008027{
8028#if 0
8029 // ARM pseudo code...
8030 if ConditionPassed() then
8031 EncodingSpecificOperations();
8032 result = R[n] EOR imm32;
8033 if d == 15 then // Can only occur for ARM encoding
8034 ALUWritePC(result); // setflags is always FALSE here
8035 else
8036 R[d] = result;
8037 if setflags then
8038 APSR.N = result<31>;
8039 APSR.Z = IsZeroBit(result);
8040 APSR.C = carry;
8041 // APSR.V unchanged
8042#endif
8043
8044 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008045
Greg Clayton7bc39082011-03-24 23:53:38 +00008046 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008047 {
8048 uint32_t Rd, Rn;
8049 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8050 bool setflags;
8051 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8052 switch (encoding)
8053 {
8054 case eEncodingT1:
8055 Rd = Bits32(opcode, 11, 8);
8056 Rn = Bits32(opcode, 19, 16);
8057 setflags = BitIsSet(opcode, 20);
8058 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8059 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8060 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008061 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008062 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8063 return false;
8064 break;
8065 case eEncodingA1:
8066 Rd = Bits32(opcode, 15, 12);
8067 Rn = Bits32(opcode, 19, 16);
8068 setflags = BitIsSet(opcode, 20);
8069 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8070 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8071 // TODO: Emulate SUBS PC, LR and related instructions.
8072 if (Rd == 15 && setflags)
8073 return false;
8074 break;
8075 default:
8076 return false;
8077 }
8078
8079 // Read the first operand.
8080 uint32_t val1 = ReadCoreReg(Rn, &success);
8081 if (!success)
8082 return false;
8083
8084 uint32_t result = val1 ^ imm32;
8085
8086 EmulateInstruction::Context context;
8087 context.type = EmulateInstruction::eContextImmediate;
8088 context.SetNoArgs ();
8089
8090 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8091 return false;
8092 }
8093 return true;
8094}
8095
8096// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8097// optionally-shifted register value, and writes the result to the destination register.
8098// It can optionally update the condition flags based on the result.
8099bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008100EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008101{
8102#if 0
8103 // ARM pseudo code...
8104 if ConditionPassed() then
8105 EncodingSpecificOperations();
8106 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8107 result = R[n] EOR shifted;
8108 if d == 15 then // Can only occur for ARM encoding
8109 ALUWritePC(result); // setflags is always FALSE here
8110 else
8111 R[d] = result;
8112 if setflags then
8113 APSR.N = result<31>;
8114 APSR.Z = IsZeroBit(result);
8115 APSR.C = carry;
8116 // APSR.V unchanged
8117#endif
8118
8119 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008120
Greg Clayton7bc39082011-03-24 23:53:38 +00008121 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008122 {
8123 uint32_t Rd, Rn, Rm;
8124 ARM_ShifterType shift_t;
8125 uint32_t shift_n; // the shift applied to the value read from Rm
8126 bool setflags;
8127 uint32_t carry;
8128 switch (encoding)
8129 {
8130 case eEncodingT1:
8131 Rd = Rn = Bits32(opcode, 2, 0);
8132 Rm = Bits32(opcode, 5, 3);
8133 setflags = !InITBlock();
8134 shift_t = SRType_LSL;
8135 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008136 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008137 case eEncodingT2:
8138 Rd = Bits32(opcode, 11, 8);
8139 Rn = Bits32(opcode, 19, 16);
8140 Rm = Bits32(opcode, 3, 0);
8141 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008142 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8143 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008144 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008145 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008146 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8147 return false;
8148 break;
8149 case eEncodingA1:
8150 Rd = Bits32(opcode, 15, 12);
8151 Rn = Bits32(opcode, 19, 16);
8152 Rm = Bits32(opcode, 3, 0);
8153 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008154 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008155 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8156 // TODO: Emulate SUBS PC, LR and related instructions.
8157 if (Rd == 15 && setflags)
8158 return false;
8159 break;
8160 default:
8161 return false;
8162 }
8163
8164 // Read the first operand.
8165 uint32_t val1 = ReadCoreReg(Rn, &success);
8166 if (!success)
8167 return false;
8168
8169 // Read the second operand.
8170 uint32_t val2 = ReadCoreReg(Rm, &success);
8171 if (!success)
8172 return false;
8173
8174 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8175 uint32_t result = val1 ^ shifted;
8176
8177 EmulateInstruction::Context context;
8178 context.type = EmulateInstruction::eContextImmediate;
8179 context.SetNoArgs ();
8180
8181 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8182 return false;
8183 }
8184 return true;
8185}
8186
Johnny Chen7c5234d2011-02-18 23:41:11 +00008187// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8188// writes the result to the destination register. It can optionally update the condition flags based
8189// on the result.
8190bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008191EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008192{
8193#if 0
8194 // ARM pseudo code...
8195 if ConditionPassed() then
8196 EncodingSpecificOperations();
8197 result = R[n] OR imm32;
8198 if d == 15 then // Can only occur for ARM encoding
8199 ALUWritePC(result); // setflags is always FALSE here
8200 else
8201 R[d] = result;
8202 if setflags then
8203 APSR.N = result<31>;
8204 APSR.Z = IsZeroBit(result);
8205 APSR.C = carry;
8206 // APSR.V unchanged
8207#endif
8208
8209 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008210
Greg Clayton7bc39082011-03-24 23:53:38 +00008211 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008212 {
8213 uint32_t Rd, Rn;
8214 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8215 bool setflags;
8216 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8217 switch (encoding)
8218 {
8219 case eEncodingT1:
8220 Rd = Bits32(opcode, 11, 8);
8221 Rn = Bits32(opcode, 19, 16);
8222 setflags = BitIsSet(opcode, 20);
8223 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008224 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008225 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008226 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008227 if (BadReg(Rd) || Rn == 13)
8228 return false;
8229 break;
8230 case eEncodingA1:
8231 Rd = Bits32(opcode, 15, 12);
8232 Rn = Bits32(opcode, 19, 16);
8233 setflags = BitIsSet(opcode, 20);
8234 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8235 // TODO: Emulate SUBS PC, LR and related instructions.
8236 if (Rd == 15 && setflags)
8237 return false;
8238 break;
8239 default:
8240 return false;
8241 }
8242
8243 // Read the first operand.
8244 uint32_t val1 = ReadCoreReg(Rn, &success);
8245 if (!success)
8246 return false;
8247
8248 uint32_t result = val1 | imm32;
8249
8250 EmulateInstruction::Context context;
8251 context.type = EmulateInstruction::eContextImmediate;
8252 context.SetNoArgs ();
8253
8254 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8255 return false;
8256 }
8257 return true;
8258}
8259
8260// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8261// value, and writes the result to the destination register. It can optionally update the condition flags based
8262// on the result.
8263bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008264EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008265{
8266#if 0
8267 // ARM pseudo code...
8268 if ConditionPassed() then
8269 EncodingSpecificOperations();
8270 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8271 result = R[n] OR shifted;
8272 if d == 15 then // Can only occur for ARM encoding
8273 ALUWritePC(result); // setflags is always FALSE here
8274 else
8275 R[d] = result;
8276 if setflags then
8277 APSR.N = result<31>;
8278 APSR.Z = IsZeroBit(result);
8279 APSR.C = carry;
8280 // APSR.V unchanged
8281#endif
8282
8283 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008284
Greg Clayton7bc39082011-03-24 23:53:38 +00008285 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008286 {
8287 uint32_t Rd, Rn, Rm;
8288 ARM_ShifterType shift_t;
8289 uint32_t shift_n; // the shift applied to the value read from Rm
8290 bool setflags;
8291 uint32_t carry;
8292 switch (encoding)
8293 {
8294 case eEncodingT1:
8295 Rd = Rn = Bits32(opcode, 2, 0);
8296 Rm = Bits32(opcode, 5, 3);
8297 setflags = !InITBlock();
8298 shift_t = SRType_LSL;
8299 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008300 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008301 case eEncodingT2:
8302 Rd = Bits32(opcode, 11, 8);
8303 Rn = Bits32(opcode, 19, 16);
8304 Rm = Bits32(opcode, 3, 0);
8305 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008306 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8307 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008308 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008309 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008310 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8311 return false;
8312 break;
8313 case eEncodingA1:
8314 Rd = Bits32(opcode, 15, 12);
8315 Rn = Bits32(opcode, 19, 16);
8316 Rm = Bits32(opcode, 3, 0);
8317 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008318 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008319 // TODO: Emulate SUBS PC, LR and related instructions.
8320 if (Rd == 15 && setflags)
8321 return false;
8322 break;
8323 default:
8324 return false;
8325 }
8326
8327 // Read the first operand.
8328 uint32_t val1 = ReadCoreReg(Rn, &success);
8329 if (!success)
8330 return false;
8331
8332 // Read the second operand.
8333 uint32_t val2 = ReadCoreReg(Rm, &success);
8334 if (!success)
8335 return false;
8336
8337 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008338 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008339
8340 EmulateInstruction::Context context;
8341 context.type = EmulateInstruction::eContextImmediate;
8342 context.SetNoArgs ();
8343
8344 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8345 return false;
8346 }
8347 return true;
8348}
8349
Johnny Chened32e7c2011-02-22 23:42:58 +00008350// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8351// the destination register. It can optionally update the condition flags based on the result.
8352bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008353EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008354{
8355#if 0
8356 // ARM pseudo code...
8357 if ConditionPassed() then
8358 EncodingSpecificOperations();
8359 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8360 if d == 15 then // Can only occur for ARM encoding
8361 ALUWritePC(result); // setflags is always FALSE here
8362 else
8363 R[d] = result;
8364 if setflags then
8365 APSR.N = result<31>;
8366 APSR.Z = IsZeroBit(result);
8367 APSR.C = carry;
8368 APSR.V = overflow;
8369#endif
8370
8371 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008372
8373 uint32_t Rd; // the destination register
8374 uint32_t Rn; // the first operand
8375 bool setflags;
8376 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8377 switch (encoding) {
8378 case eEncodingT1:
8379 Rd = Bits32(opcode, 2, 0);
8380 Rn = Bits32(opcode, 5, 3);
8381 setflags = !InITBlock();
8382 imm32 = 0;
8383 break;
8384 case eEncodingT2:
8385 Rd = Bits32(opcode, 11, 8);
8386 Rn = Bits32(opcode, 19, 16);
8387 setflags = BitIsSet(opcode, 20);
8388 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8389 if (BadReg(Rd) || BadReg(Rn))
8390 return false;
8391 break;
8392 case eEncodingA1:
8393 Rd = Bits32(opcode, 15, 12);
8394 Rn = Bits32(opcode, 19, 16);
8395 setflags = BitIsSet(opcode, 20);
8396 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8397 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8398 // TODO: Emulate SUBS PC, LR and related instructions.
8399 if (Rd == 15 && setflags)
8400 return false;
8401 break;
8402 default:
8403 return false;
8404 }
8405 // Read the register value from the operand register Rn.
8406 uint32_t reg_val = ReadCoreReg(Rn, &success);
8407 if (!success)
8408 return false;
8409
8410 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8411
8412 EmulateInstruction::Context context;
8413 context.type = EmulateInstruction::eContextImmediate;
8414 context.SetNoArgs ();
8415
8416 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8417 return false;
8418
8419 return true;
8420}
8421
8422// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8423// result to the destination register. It can optionally update the condition flags based on the result.
8424bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008425EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008426{
8427#if 0
8428 // ARM pseudo code...
8429 if ConditionPassed() then
8430 EncodingSpecificOperations();
8431 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8432 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8433 if d == 15 then // Can only occur for ARM encoding
8434 ALUWritePC(result); // setflags is always FALSE here
8435 else
8436 R[d] = result;
8437 if setflags then
8438 APSR.N = result<31>;
8439 APSR.Z = IsZeroBit(result);
8440 APSR.C = carry;
8441 APSR.V = overflow;
8442#endif
8443
8444 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008445
8446 uint32_t Rd; // the destination register
8447 uint32_t Rn; // the first operand
8448 uint32_t Rm; // the second operand
8449 bool setflags;
8450 ARM_ShifterType shift_t;
8451 uint32_t shift_n; // the shift applied to the value read from Rm
8452 switch (encoding) {
8453 case eEncodingT1:
8454 Rd = Bits32(opcode, 11, 8);
8455 Rn = Bits32(opcode, 19, 16);
8456 Rm = Bits32(opcode, 3, 0);
8457 setflags = BitIsSet(opcode, 20);
8458 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8459 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8460 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8461 return false;
8462 break;
8463 case eEncodingA1:
8464 Rd = Bits32(opcode, 15, 12);
8465 Rn = Bits32(opcode, 19, 16);
8466 Rm = Bits32(opcode, 3, 0);
8467 setflags = BitIsSet(opcode, 20);
8468 shift_n = DecodeImmShiftARM(opcode, shift_t);
8469 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8470 // TODO: Emulate SUBS PC, LR and related instructions.
8471 if (Rd == 15 && setflags)
8472 return false;
8473 break;
8474 default:
8475 return false;
8476 }
8477 // Read the register value from register Rn.
8478 uint32_t val1 = ReadCoreReg(Rn, &success);
8479 if (!success)
8480 return false;
8481
8482 // Read the register value from register Rm.
8483 uint32_t val2 = ReadCoreReg(Rm, &success);
8484 if (!success)
8485 return false;
8486
8487 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8488 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8489
8490 EmulateInstruction::Context context;
8491 context.type = EmulateInstruction::eContextImmediate;
8492 context.SetNoArgs();
8493 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8494 return false;
8495
8496 return true;
8497}
8498
Johnny Chen90e607b2011-02-23 00:07:09 +00008499// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8500// an immediate value, and writes the result to the destination register. It can optionally update the condition
8501// flags based on the result.
8502bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008503EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008504{
8505#if 0
8506 // ARM pseudo code...
8507 if ConditionPassed() then
8508 EncodingSpecificOperations();
8509 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8510 if d == 15 then
8511 ALUWritePC(result); // setflags is always FALSE here
8512 else
8513 R[d] = result;
8514 if setflags then
8515 APSR.N = result<31>;
8516 APSR.Z = IsZeroBit(result);
8517 APSR.C = carry;
8518 APSR.V = overflow;
8519#endif
8520
8521 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008522
8523 uint32_t Rd; // the destination register
8524 uint32_t Rn; // the first operand
8525 bool setflags;
8526 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8527 switch (encoding) {
8528 case eEncodingA1:
8529 Rd = Bits32(opcode, 15, 12);
8530 Rn = Bits32(opcode, 19, 16);
8531 setflags = BitIsSet(opcode, 20);
8532 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8534 // TODO: Emulate SUBS PC, LR and related instructions.
8535 if (Rd == 15 && setflags)
8536 return false;
8537 break;
8538 default:
8539 return false;
8540 }
8541 // Read the register value from the operand register Rn.
8542 uint32_t reg_val = ReadCoreReg(Rn, &success);
8543 if (!success)
8544 return false;
8545
8546 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8547
8548 EmulateInstruction::Context context;
8549 context.type = EmulateInstruction::eContextImmediate;
8550 context.SetNoArgs ();
8551
8552 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8553 return false;
8554
8555 return true;
8556}
8557
8558// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8559// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8560// condition flags based on the result.
8561bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008562EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008563{
8564#if 0
8565 // ARM pseudo code...
8566 if ConditionPassed() then
8567 EncodingSpecificOperations();
8568 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8569 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8570 if d == 15 then
8571 ALUWritePC(result); // setflags is always FALSE here
8572 else
8573 R[d] = result;
8574 if setflags then
8575 APSR.N = result<31>;
8576 APSR.Z = IsZeroBit(result);
8577 APSR.C = carry;
8578 APSR.V = overflow;
8579#endif
8580
8581 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008582
8583 uint32_t Rd; // the destination register
8584 uint32_t Rn; // the first operand
8585 uint32_t Rm; // the second operand
8586 bool setflags;
8587 ARM_ShifterType shift_t;
8588 uint32_t shift_n; // the shift applied to the value read from Rm
8589 switch (encoding) {
8590 case eEncodingA1:
8591 Rd = Bits32(opcode, 15, 12);
8592 Rn = Bits32(opcode, 19, 16);
8593 Rm = Bits32(opcode, 3, 0);
8594 setflags = BitIsSet(opcode, 20);
8595 shift_n = DecodeImmShiftARM(opcode, shift_t);
8596 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8597 // TODO: Emulate SUBS PC, LR and related instructions.
8598 if (Rd == 15 && setflags)
8599 return false;
8600 break;
8601 default:
8602 return false;
8603 }
8604 // Read the register value from register Rn.
8605 uint32_t val1 = ReadCoreReg(Rn, &success);
8606 if (!success)
8607 return false;
8608
8609 // Read the register value from register Rm.
8610 uint32_t val2 = ReadCoreReg(Rm, &success);
8611 if (!success)
8612 return false;
8613
8614 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8615 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8616
8617 EmulateInstruction::Context context;
8618 context.type = EmulateInstruction::eContextImmediate;
8619 context.SetNoArgs();
8620 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8621 return false;
8622
8623 return true;
8624}
8625
Johnny Chen9b381772011-02-23 01:01:21 +00008626// Subtract with Carry (immediate) subtracts an immediate value and the value of
8627// NOT (Carry flag) from a register value, and writes the result to the destination register.
8628// It can optionally update the condition flags based on the result.
8629bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008630EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008631{
8632#if 0
8633 // ARM pseudo code...
8634 if ConditionPassed() then
8635 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008636 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008637 if d == 15 then // Can only occur for ARM encoding
8638 ALUWritePC(result); // setflags is always FALSE here
8639 else
8640 R[d] = result;
8641 if setflags then
8642 APSR.N = result<31>;
8643 APSR.Z = IsZeroBit(result);
8644 APSR.C = carry;
8645 APSR.V = overflow;
8646#endif
8647
8648 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008649
8650 uint32_t Rd; // the destination register
8651 uint32_t Rn; // the first operand
8652 bool setflags;
8653 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8654 switch (encoding) {
8655 case eEncodingT1:
8656 Rd = Bits32(opcode, 11, 8);
8657 Rn = Bits32(opcode, 19, 16);
8658 setflags = BitIsSet(opcode, 20);
8659 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8660 if (BadReg(Rd) || BadReg(Rn))
8661 return false;
8662 break;
8663 case eEncodingA1:
8664 Rd = Bits32(opcode, 15, 12);
8665 Rn = Bits32(opcode, 19, 16);
8666 setflags = BitIsSet(opcode, 20);
8667 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8668 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8669 // TODO: Emulate SUBS PC, LR and related instructions.
8670 if (Rd == 15 && setflags)
8671 return false;
8672 break;
8673 default:
8674 return false;
8675 }
8676 // Read the register value from the operand register Rn.
8677 uint32_t reg_val = ReadCoreReg(Rn, &success);
8678 if (!success)
8679 return false;
8680
8681 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8682
8683 EmulateInstruction::Context context;
8684 context.type = EmulateInstruction::eContextImmediate;
8685 context.SetNoArgs ();
8686
8687 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8688 return false;
8689
8690 return true;
8691}
8692
8693// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8694// NOT (Carry flag) from a register value, and writes the result to the destination register.
8695// It can optionally update the condition flags based on the result.
8696bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008697EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008698{
8699#if 0
8700 // ARM pseudo code...
8701 if ConditionPassed() then
8702 EncodingSpecificOperations();
8703 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8704 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8705 if d == 15 then // Can only occur for ARM encoding
8706 ALUWritePC(result); // setflags is always FALSE here
8707 else
8708 R[d] = result;
8709 if setflags then
8710 APSR.N = result<31>;
8711 APSR.Z = IsZeroBit(result);
8712 APSR.C = carry;
8713 APSR.V = overflow;
8714#endif
8715
8716 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008717
8718 uint32_t Rd; // the destination register
8719 uint32_t Rn; // the first operand
8720 uint32_t Rm; // the second operand
8721 bool setflags;
8722 ARM_ShifterType shift_t;
8723 uint32_t shift_n; // the shift applied to the value read from Rm
8724 switch (encoding) {
8725 case eEncodingT1:
8726 Rd = Rn = Bits32(opcode, 2, 0);
8727 Rm = Bits32(opcode, 5, 3);
8728 setflags = !InITBlock();
8729 shift_t = SRType_LSL;
8730 shift_n = 0;
8731 break;
8732 case eEncodingT2:
8733 Rd = Bits32(opcode, 11, 8);
8734 Rn = Bits32(opcode, 19, 16);
8735 Rm = Bits32(opcode, 3, 0);
8736 setflags = BitIsSet(opcode, 20);
8737 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8738 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8739 return false;
8740 break;
8741 case eEncodingA1:
8742 Rd = Bits32(opcode, 15, 12);
8743 Rn = Bits32(opcode, 19, 16);
8744 Rm = Bits32(opcode, 3, 0);
8745 setflags = BitIsSet(opcode, 20);
8746 shift_n = DecodeImmShiftARM(opcode, shift_t);
8747 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8748 // TODO: Emulate SUBS PC, LR and related instructions.
8749 if (Rd == 15 && setflags)
8750 return false;
8751 break;
8752 default:
8753 return false;
8754 }
8755 // Read the register value from register Rn.
8756 uint32_t val1 = ReadCoreReg(Rn, &success);
8757 if (!success)
8758 return false;
8759
8760 // Read the register value from register Rm.
8761 uint32_t val2 = ReadCoreReg(Rm, &success);
8762 if (!success)
8763 return false;
8764
8765 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8766 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8767
8768 EmulateInstruction::Context context;
8769 context.type = EmulateInstruction::eContextImmediate;
8770 context.SetNoArgs();
8771 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8772 return false;
8773
8774 return true;
8775}
8776
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008777// This instruction subtracts an immediate value from a register value, and writes the result
8778// to the destination register. It can optionally update the condition flags based on the result.
8779bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008780EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008781{
8782#if 0
8783 // ARM pseudo code...
8784 if ConditionPassed() then
8785 EncodingSpecificOperations();
8786 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8787 R[d] = result;
8788 if setflags then
8789 APSR.N = result<31>;
8790 APSR.Z = IsZeroBit(result);
8791 APSR.C = carry;
8792 APSR.V = overflow;
8793#endif
8794
8795 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008796
8797 uint32_t Rd; // the destination register
8798 uint32_t Rn; // the first operand
8799 bool setflags;
8800 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8801 switch (encoding) {
8802 case eEncodingT1:
8803 Rd = Bits32(opcode, 2, 0);
8804 Rn = Bits32(opcode, 5, 3);
8805 setflags = !InITBlock();
8806 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8807 break;
8808 case eEncodingT2:
8809 Rd = Rn = Bits32(opcode, 10, 8);
8810 setflags = !InITBlock();
8811 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8812 break;
8813 case eEncodingT3:
8814 Rd = Bits32(opcode, 11, 8);
8815 Rn = Bits32(opcode, 19, 16);
8816 setflags = BitIsSet(opcode, 20);
8817 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8818
8819 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8820 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008821 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008822
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008823 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008824 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008825 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008826
8827 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8828 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8829 return false;
8830 break;
8831 case eEncodingT4:
8832 Rd = Bits32(opcode, 11, 8);
8833 Rn = Bits32(opcode, 19, 16);
8834 setflags = BitIsSet(opcode, 20);
8835 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8836
8837 // if Rn == '1111' then SEE ADR;
8838 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008839 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008840
8841 // if Rn == '1101' then SEE SUB (SP minus immediate);
8842 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008843 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008844
8845 if (BadReg(Rd))
8846 return false;
8847 break;
8848 default:
8849 return false;
8850 }
8851 // Read the register value from the operand register Rn.
8852 uint32_t reg_val = ReadCoreReg(Rn, &success);
8853 if (!success)
8854 return false;
8855
8856 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8857
8858 EmulateInstruction::Context context;
8859 context.type = EmulateInstruction::eContextImmediate;
8860 context.SetNoArgs ();
8861
8862 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8863 return false;
8864
8865 return true;
8866}
8867
8868// This instruction subtracts an immediate value from a register value, and writes the result
8869// to the destination register. It can optionally update the condition flags based on the result.
8870bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008871EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008872{
8873#if 0
8874 // ARM pseudo code...
8875 if ConditionPassed() then
8876 EncodingSpecificOperations();
8877 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8878 if d == 15 then
8879 ALUWritePC(result); // setflags is always FALSE here
8880 else
8881 R[d] = result;
8882 if setflags then
8883 APSR.N = result<31>;
8884 APSR.Z = IsZeroBit(result);
8885 APSR.C = carry;
8886 APSR.V = overflow;
8887#endif
8888
8889 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008890
8891 uint32_t Rd; // the destination register
8892 uint32_t Rn; // the first operand
8893 bool setflags;
8894 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8895 switch (encoding) {
8896 case eEncodingA1:
8897 Rd = Bits32(opcode, 15, 12);
8898 Rn = Bits32(opcode, 19, 16);
8899 setflags = BitIsSet(opcode, 20);
8900 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8901
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008902 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008903 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008904 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008905
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008906 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008907 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008908 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008909
8910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8911 // TODO: Emulate SUBS PC, LR and related instructions.
8912 if (Rd == 15 && setflags)
8913 return false;
8914 break;
8915 default:
8916 return false;
8917 }
8918 // Read the register value from the operand register Rn.
8919 uint32_t reg_val = ReadCoreReg(Rn, &success);
8920 if (!success)
8921 return false;
8922
8923 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8924
8925 EmulateInstruction::Context context;
8926 context.type = EmulateInstruction::eContextImmediate;
8927 context.SetNoArgs ();
8928
8929 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8930 return false;
8931
8932 return true;
8933}
8934
Johnny Chen2115b412011-02-21 23:42:44 +00008935// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8936// immediate value. It updates the condition flags based on the result, and discards the result.
8937bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008938EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008939{
8940#if 0
8941 // ARM pseudo code...
8942 if ConditionPassed() then
8943 EncodingSpecificOperations();
8944 result = R[n] EOR imm32;
8945 APSR.N = result<31>;
8946 APSR.Z = IsZeroBit(result);
8947 APSR.C = carry;
8948 // APSR.V unchanged
8949#endif
8950
8951 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008952
Greg Clayton7bc39082011-03-24 23:53:38 +00008953 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008954 {
8955 uint32_t Rn;
8956 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8957 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8958 switch (encoding)
8959 {
8960 case eEncodingT1:
8961 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008962 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008963 if (BadReg(Rn))
8964 return false;
8965 break;
8966 case eEncodingA1:
8967 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008968 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008969 break;
8970 default:
8971 return false;
8972 }
8973
8974 // Read the first operand.
8975 uint32_t val1 = ReadCoreReg(Rn, &success);
8976 if (!success)
8977 return false;
8978
8979 uint32_t result = val1 ^ imm32;
8980
8981 EmulateInstruction::Context context;
8982 context.type = EmulateInstruction::eContextImmediate;
8983 context.SetNoArgs ();
8984
8985 if (!WriteFlags(context, result, carry))
8986 return false;
8987 }
8988 return true;
8989}
8990
8991// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8992// optionally-shifted register value. It updates the condition flags based on the result, and discards
8993// the result.
8994bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008995EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008996{
8997#if 0
8998 // ARM pseudo code...
8999 if ConditionPassed() then
9000 EncodingSpecificOperations();
9001 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9002 result = R[n] EOR shifted;
9003 APSR.N = result<31>;
9004 APSR.Z = IsZeroBit(result);
9005 APSR.C = carry;
9006 // APSR.V unchanged
9007#endif
9008
9009 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009010
Greg Clayton7bc39082011-03-24 23:53:38 +00009011 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009012 {
9013 uint32_t Rn, Rm;
9014 ARM_ShifterType shift_t;
9015 uint32_t shift_n; // the shift applied to the value read from Rm
9016 uint32_t carry;
9017 switch (encoding)
9018 {
9019 case eEncodingT1:
9020 Rn = Bits32(opcode, 19, 16);
9021 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009022 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009023 if (BadReg(Rn) || BadReg(Rm))
9024 return false;
9025 break;
9026 case eEncodingA1:
9027 Rn = Bits32(opcode, 19, 16);
9028 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009029 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009030 break;
9031 default:
9032 return false;
9033 }
9034
9035 // Read the first operand.
9036 uint32_t val1 = ReadCoreReg(Rn, &success);
9037 if (!success)
9038 return false;
9039
9040 // Read the second operand.
9041 uint32_t val2 = ReadCoreReg(Rm, &success);
9042 if (!success)
9043 return false;
9044
9045 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9046 uint32_t result = val1 ^ shifted;
9047
9048 EmulateInstruction::Context context;
9049 context.type = EmulateInstruction::eContextImmediate;
9050 context.SetNoArgs ();
9051
9052 if (!WriteFlags(context, result, carry))
9053 return false;
9054 }
9055 return true;
9056}
9057
Johnny Chende3cce32011-02-21 21:24:49 +00009058// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9059// It updates the condition flags based on the result, and discards the result.
9060bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009061EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009062{
9063#if 0
9064 // ARM pseudo code...
9065 if ConditionPassed() then
9066 EncodingSpecificOperations();
9067 result = R[n] AND imm32;
9068 APSR.N = result<31>;
9069 APSR.Z = IsZeroBit(result);
9070 APSR.C = carry;
9071 // APSR.V unchanged
9072#endif
9073
9074 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009075
Greg Clayton7bc39082011-03-24 23:53:38 +00009076 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009077 {
9078 uint32_t Rn;
9079 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9080 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9081 switch (encoding)
9082 {
9083 case eEncodingT1:
9084 Rn = Bits32(opcode, 19, 16);
9085 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9086 if (BadReg(Rn))
9087 return false;
9088 break;
9089 case eEncodingA1:
9090 Rn = Bits32(opcode, 19, 16);
9091 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9092 break;
9093 default:
9094 return false;
9095 }
9096
9097 // Read the first operand.
9098 uint32_t val1 = ReadCoreReg(Rn, &success);
9099 if (!success)
9100 return false;
9101
9102 uint32_t result = val1 & imm32;
9103
9104 EmulateInstruction::Context context;
9105 context.type = EmulateInstruction::eContextImmediate;
9106 context.SetNoArgs ();
9107
9108 if (!WriteFlags(context, result, carry))
9109 return false;
9110 }
9111 return true;
9112}
9113
9114// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9115// It updates the condition flags based on the result, and discards the result.
9116bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009117EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009118{
9119#if 0
9120 // ARM pseudo code...
9121 if ConditionPassed() then
9122 EncodingSpecificOperations();
9123 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9124 result = R[n] AND shifted;
9125 APSR.N = result<31>;
9126 APSR.Z = IsZeroBit(result);
9127 APSR.C = carry;
9128 // APSR.V unchanged
9129#endif
9130
9131 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009132
Greg Clayton7bc39082011-03-24 23:53:38 +00009133 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009134 {
9135 uint32_t Rn, Rm;
9136 ARM_ShifterType shift_t;
9137 uint32_t shift_n; // the shift applied to the value read from Rm
9138 uint32_t carry;
9139 switch (encoding)
9140 {
9141 case eEncodingT1:
9142 Rn = Bits32(opcode, 2, 0);
9143 Rm = Bits32(opcode, 5, 3);
9144 shift_t = SRType_LSL;
9145 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009146 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009147 case eEncodingT2:
9148 Rn = Bits32(opcode, 19, 16);
9149 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009150 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009151 if (BadReg(Rn) || BadReg(Rm))
9152 return false;
9153 break;
9154 case eEncodingA1:
9155 Rn = Bits32(opcode, 19, 16);
9156 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009157 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009158 break;
9159 default:
9160 return false;
9161 }
9162
9163 // Read the first operand.
9164 uint32_t val1 = ReadCoreReg(Rn, &success);
9165 if (!success)
9166 return false;
9167
9168 // Read the second operand.
9169 uint32_t val2 = ReadCoreReg(Rm, &success);
9170 if (!success)
9171 return false;
9172
9173 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9174 uint32_t result = val1 & shifted;
9175
9176 EmulateInstruction::Context context;
9177 context.type = EmulateInstruction::eContextImmediate;
9178 context.SetNoArgs ();
9179
9180 if (!WriteFlags(context, result, carry))
9181 return false;
9182 }
9183 return true;
9184}
Caroline Ticed05b4902011-03-29 21:24:06 +00009185
9186// A8.6.216 SUB (SP minus register)
9187bool
9188EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9189{
9190#if 0
9191 if ConditionPassed() then
9192 EncodingSpecificOperations();
9193 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9194 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9195 if d == 15 then // Can only occur for ARM encoding
9196 ALUWritePC(result); // setflags is always FALSE here
9197 else
9198 R[d] = result;
9199 if setflags then
9200 APSR.N = result<31>;
9201 APSR.Z = IsZeroBit(result);
9202 APSR.C = carry;
9203 APSR.V = overflow;
9204#endif
9205
9206 bool success = false;
9207
9208 if (ConditionPassed(opcode))
9209 {
9210 uint32_t d;
9211 uint32_t m;
9212 bool setflags;
9213 ARM_ShifterType shift_t;
9214 uint32_t shift_n;
9215
9216 switch (encoding)
9217 {
9218 case eEncodingT1:
9219 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9220 d = Bits32 (opcode, 11, 8);
9221 m = Bits32 (opcode, 3, 0);
9222 setflags = BitIsSet (opcode, 20);
9223
9224 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9225 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9226
9227 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9228 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9229 return false;
9230
9231 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9232 if ((d == 15) || BadReg (m))
9233 return false;
9234 break;
9235
9236 case eEncodingA1:
9237 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9238 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9239 d = Bits32 (opcode, 15, 12);
9240 m = Bits32 (opcode, 3, 0);
9241 setflags = BitIsSet (opcode, 20);
9242
9243 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9244 shift_n = DecodeImmShiftARM (opcode, shift_t);
9245 break;
9246
9247 default:
9248 return false;
9249 }
9250
9251 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9252 uint32_t Rm = ReadCoreReg (m, &success);
9253 if (!success)
9254 return false;
9255
9256 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9257
9258 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9259 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9260 if (!success)
9261 return false;
9262
9263 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9264
9265 EmulateInstruction::Context context;
9266 context.type = eContextSubtraction;
9267 Register sp_reg;
9268 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9269 Register dwarf_reg;
9270 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9271 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9272
Caroline Ticeef440002011-03-30 05:40:56 +00009273 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009274 return false;
9275 }
9276 return true;
9277}
9278
9279
9280// A8.6.7 ADD (register-shifted register)
9281bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009282EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009283{
9284#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009285 if ConditionPassed() then
9286 EncodingSpecificOperations();
9287 shift_n = UInt(R[s]<7:0>);
9288 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9289 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9290 R[d] = result;
9291 if setflags then
9292 APSR.N = result<31>;
9293 APSR.Z = IsZeroBit(result);
9294 APSR.C = carry;
9295 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009296#endif
9297
Caroline Ticec08ed382011-03-29 23:03:16 +00009298 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009299
9300 if (ConditionPassed(opcode))
9301 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009302 uint32_t d;
9303 uint32_t n;
9304 uint32_t m;
9305 uint32_t s;
9306 bool setflags;
9307 ARM_ShifterType shift_t;
9308
Caroline Ticed05b4902011-03-29 21:24:06 +00009309 switch (encoding)
9310 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009311 case eEncodingA1:
9312 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9313 d = Bits32 (opcode, 15, 12);
9314 n = Bits32 (opcode, 19, 16);
9315 m = Bits32 (opcode, 3, 0);
9316 s = Bits32 (opcode, 11, 8);
9317
9318 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9319 setflags = BitIsSet (opcode, 20);
9320 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9321
9322 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9323 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9324 return false;
9325 break;
9326
9327 default:
9328 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009329 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009330
9331 // shift_n = UInt(R[s]<7:0>);
9332 uint32_t Rs = ReadCoreReg (s, &success);
9333 if (!success)
9334 return false;
9335
9336 uint32_t shift_n = Bits32 (Rs, 7, 0);
9337
9338 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9339 uint32_t Rm = ReadCoreReg (m, &success);
9340 if (!success)
9341 return false;
9342
9343 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9344
9345 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9346 uint32_t Rn = ReadCoreReg (n, &success);
9347 if (!success)
9348 return false;
9349
9350 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9351
9352 // R[d] = result;
9353 EmulateInstruction::Context context;
9354 context.type = eContextAddition;
9355 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009356 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009357 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009358 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009359
9360 context.SetRegisterRegisterOperands (reg_n, reg_m);
9361
9362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9363 return false;
9364
9365 // if setflags then
9366 // APSR.N = result<31>;
9367 // APSR.Z = IsZeroBit(result);
9368 // APSR.C = carry;
9369 // APSR.V = overflow;
9370 if (setflags)
9371 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009372 }
9373 return true;
9374}
9375
9376// A8.6.213 SUB (register)
9377bool
9378EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9379{
9380#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009381 if ConditionPassed() then
9382 EncodingSpecificOperations();
9383 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9384 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9385 if d == 15 then // Can only occur for ARM encoding
9386 ALUWritePC(result); // setflags is always FALSE here
9387 else
9388 R[d] = result;
9389 if setflags then
9390 APSR.N = result<31>;
9391 APSR.Z = IsZeroBit(result);
9392 APSR.C = carry;
9393 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009394#endif
9395
Caroline Tice4cccd532011-03-29 23:44:20 +00009396 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009397
9398 if (ConditionPassed(opcode))
9399 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009400 uint32_t d;
9401 uint32_t n;
9402 uint32_t m;
9403 bool setflags;
9404 ARM_ShifterType shift_t;
9405 uint32_t shift_n;
9406
Caroline Ticed05b4902011-03-29 21:24:06 +00009407 switch (encoding)
9408 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009409 case eEncodingT1:
9410 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9411 d = Bits32 (opcode, 2, 0);
9412 n = Bits32 (opcode, 5, 3);
9413 m = Bits32 (opcode, 8, 6);
9414 setflags = !InITBlock();
9415
9416 // (shift_t, shift_n) = (SRType_LSL, 0);
9417 shift_t = SRType_LSL;
9418 shift_n = 0;
9419
9420 break;
9421
9422 case eEncodingT2:
9423 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9424 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9425 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9426 d = Bits32 (opcode, 11, 8);
9427 n = Bits32 (opcode, 19, 16);
9428 m = Bits32 (opcode, 3, 0);
9429 setflags = BitIsSet (opcode, 20);
9430
9431 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9432 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9433
9434 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9435 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9436 return false;
9437
9438 break;
9439
9440 case eEncodingA1:
9441 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9442 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9443 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9444 d = Bits32 (opcode, 15, 12);
9445 n = Bits32 (opcode, 19, 16);
9446 m = Bits32 (opcode, 3, 0);
9447 setflags = BitIsSet (opcode, 20);
9448
9449 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9450 shift_n = DecodeImmShiftARM (opcode, shift_t);
9451
9452 break;
9453
9454 default:
9455 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009456 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009457
9458 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9459 uint32_t Rm = ReadCoreReg (m, &success);
9460 if (!success)
9461 return false;
9462
9463 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9464
9465 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9466 uint32_t Rn = ReadCoreReg (n, &success);
9467 if (!success)
9468 return false;
9469
9470 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9471
9472 // if d == 15 then // Can only occur for ARM encoding
9473 // ALUWritePC(result); // setflags is always FALSE here
9474 // else
9475 // R[d] = result;
9476 // if setflags then
9477 // APSR.N = result<31>;
9478 // APSR.Z = IsZeroBit(result);
9479 // APSR.C = carry;
9480 // APSR.V = overflow;
9481
9482 EmulateInstruction::Context context;
9483 context.type = eContextSubtraction;
9484 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009485 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009486 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009487 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009488 context.SetRegisterRegisterOperands (reg_n, reg_m);
9489
Caroline Ticeef440002011-03-30 05:40:56 +00009490 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009491 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009492 }
9493 return true;
9494}
Caroline Tice4cccd532011-03-29 23:44:20 +00009495
Caroline Ticed05b4902011-03-29 21:24:06 +00009496// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009497// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9498// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009499bool
9500EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9501{
9502#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009503 if ConditionPassed() then
9504 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9505 address = R[n] + imm32;
9506 if ExclusiveMonitorsPass(address,4) then
9507 MemA[address,4] = R[t];
9508 R[d] = 0;
9509 else
9510 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009511#endif
9512
Caroline Tice5168b6c2011-03-30 05:15:46 +00009513 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009514
9515 if (ConditionPassed(opcode))
9516 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009517 uint32_t d;
9518 uint32_t t;
9519 uint32_t n;
9520 uint32_t imm32;
9521 const uint32_t addr_byte_size = GetAddressByteSize();
9522
Caroline Ticed05b4902011-03-29 21:24:06 +00009523 switch (encoding)
9524 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009525 case eEncodingT1:
9526 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9527 d = Bits32 (opcode, 11, 8);
9528 t = Bits32 (opcode, 15, 12);
9529 n = Bits32 (opcode, 19, 16);
9530 imm32 = Bits32 (opcode, 7, 0) << 2;
9531
9532 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9533 if (BadReg (d) || BadReg (t) || (n == 15))
9534 return false;
9535
9536 // if d == n || d == t then UNPREDICTABLE;
9537 if ((d == n) || (d == t))
9538 return false;
9539
9540 break;
9541
9542 case eEncodingA1:
9543 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9544 d = Bits32 (opcode, 15, 12);
9545 t = Bits32 (opcode, 3, 0);
9546 n = Bits32 (opcode, 19, 16);
9547 imm32 = 0;
9548
9549 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9550 if ((d == 15) || (t == 15) || (n == 15))
9551 return false;
9552
9553 // if d == n || d == t then UNPREDICTABLE;
9554 if ((d == n) || (d == t))
9555 return false;
9556
9557 break;
9558
9559 default:
9560 return false;
9561 }
9562
9563 // address = R[n] + imm32;
9564 uint32_t Rn = ReadCoreReg (n, &success);
9565 if (!success)
9566 return false;
9567
9568 addr_t address = Rn + imm32;
9569
9570 Register base_reg;
9571 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9572 Register data_reg;
9573 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9574 EmulateInstruction::Context context;
9575 context.type = eContextRegisterStore;
9576 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9577
9578 // if ExclusiveMonitorsPass(address,4) then
9579 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9580 // always return true.
9581 if (true)
9582 {
9583 // MemA[address,4] = R[t];
9584 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9585 if (!success)
9586 return false;
9587
9588 if (!MemAWrite (context, address, Rt, addr_byte_size))
9589 return false;
9590
9591 // R[d] = 0;
9592 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9593 return false;
9594 }
9595 else
9596 {
9597 // R[d] = 1;
9598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9599 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009600 }
9601 }
9602 return true;
9603}
9604
9605// A8.6.197 STRB (immediate, ARM)
9606bool
9607EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9608{
9609#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009610 if ConditionPassed() then
9611 EncodingSpecificOperations();
9612 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9613 address = if index then offset_addr else R[n];
9614 MemU[address,1] = R[t]<7:0>;
9615 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009616#endif
9617
Caroline Ticeef440002011-03-30 05:40:56 +00009618 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009619
9620 if (ConditionPassed(opcode))
9621 {
Caroline Ticeef440002011-03-30 05:40:56 +00009622 uint32_t t;
9623 uint32_t n;
9624 uint32_t imm32;
9625 bool index;
9626 bool add;
9627 bool wback;
9628
Caroline Ticed05b4902011-03-29 21:24:06 +00009629 switch (encoding)
9630 {
Caroline Ticeef440002011-03-30 05:40:56 +00009631 case eEncodingA1:
9632 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9633 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9634 t = Bits32 (opcode, 15, 12);
9635 n = Bits32 (opcode, 19, 16);
9636 imm32 = Bits32 (opcode, 11, 0);
9637
9638 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9639 index = BitIsSet (opcode, 24);
9640 add = BitIsSet (opcode, 23);
9641 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9642
9643 // if t == 15 then UNPREDICTABLE;
9644 if (t == 15)
9645 return false;
9646
9647 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9648 if (wback && ((n == 15) || (n == t)))
9649 return false;
9650
9651 break;
9652
9653 default:
9654 return false;
9655 }
9656
9657 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9658 uint32_t Rn = ReadCoreReg (n, &success);
9659 if (!success)
9660 return false;
9661
9662 addr_t offset_addr;
9663 if (add)
9664 offset_addr = Rn + imm32;
9665 else
9666 offset_addr = Rn - imm32;
9667
9668 // address = if index then offset_addr else R[n];
9669 addr_t address;
9670 if (index)
9671 address = offset_addr;
9672 else
9673 address = Rn;
9674
9675 // MemU[address,1] = R[t]<7:0>;
9676 uint32_t Rt = ReadCoreReg (t, &success);
9677 if (!success)
9678 return false;
9679
9680 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009681 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009682 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009683 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009684 EmulateInstruction::Context context;
9685 context.type = eContextRegisterStore;
9686 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9687
9688 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9689 return false;
9690
9691 // if wback then R[n] = offset_addr;
9692 if (wback)
9693 {
9694 if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9695 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009696 }
9697 }
9698 return true;
9699}
9700
9701// A8.6.194 STR (immediate, ARM)
9702bool
9703EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9704{
9705#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009706 if ConditionPassed() then
9707 EncodingSpecificOperations();
9708 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9709 address = if index then offset_addr else R[n];
9710 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9711 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009712#endif
9713
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009714 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009715
9716 if (ConditionPassed(opcode))
9717 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009718 uint32_t t;
9719 uint32_t n;
9720 uint32_t imm32;
9721 bool index;
9722 bool add;
9723 bool wback;
9724
9725 const uint32_t addr_byte_size = GetAddressByteSize();
9726
Caroline Ticed05b4902011-03-29 21:24:06 +00009727 switch (encoding)
9728 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009729 case eEncodingA1:
9730 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9731 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9732 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9733 t = Bits32 (opcode, 15, 12);
9734 n = Bits32 (opcode, 19, 16);
9735 imm32 = Bits32 (opcode, 11, 0);
9736
9737 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9738 index = BitIsSet (opcode, 24);
9739 add = BitIsSet (opcode, 23);
9740 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9741
9742 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9743 if (wback && ((n == 15) || (n == t)))
9744 return false;
9745
9746 break;
9747
9748 default:
9749 return false;
9750 }
9751
9752 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9753 uint32_t Rn = ReadCoreReg (n, &success);
9754 if (!success)
9755 return false;
9756
9757 addr_t offset_addr;
9758 if (add)
9759 offset_addr = Rn + imm32;
9760 else
9761 offset_addr = Rn - imm32;
9762
9763 // address = if index then offset_addr else R[n];
9764 addr_t address;
9765 if (index)
9766 address = offset_addr;
9767 else
9768 address = Rn;
9769
9770 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009771 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009772 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009773 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009774 EmulateInstruction::Context context;
9775 context.type = eContextRegisterStore;
9776 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9777
9778 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9779 uint32_t Rt = ReadCoreReg (t, &success);
9780 if (!success)
9781 return false;
9782
9783 if (t == 15)
9784 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009785 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009786 if (!success)
9787 return false;
9788
9789 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9790 return false;
9791 }
9792 else
9793 {
9794 if (!MemUWrite (context, address, Rt, addr_byte_size))
9795 return false;
9796 }
9797
9798 // if wback then R[n] = offset_addr;
9799 if (wback)
9800 {
9801 context.type = eContextAdjustBaseRegister;
9802 context.SetImmediate (offset_addr);
9803
9804 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9805 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009806 }
9807 }
9808 return true;
9809}
9810
Caroline Ticed05b4902011-03-29 21:24:06 +00009811// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009812// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9813// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +00009814bool
9815EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9816{
9817#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009818 if ConditionPassed() then
9819 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9820 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9821 address = if index then offset_addr else R[n];
9822 R[t] = MemA[address,4];
9823 R[t2] = MemA[address+4,4];
9824 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009825#endif
9826
Caroline Tice1697dd72011-03-30 17:11:45 +00009827 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009828
9829 if (ConditionPassed(opcode))
9830 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009831 uint32_t t;
9832 uint32_t t2;
9833 uint32_t n;
9834 uint32_t imm32;
9835 bool index;
9836 bool add;
9837 bool wback;
9838
Caroline Ticed05b4902011-03-29 21:24:06 +00009839 switch (encoding)
9840 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009841 case eEncodingT1:
9842 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9843 //if Rn == ‘1111’ then SEE LDRD (literal);
9844 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9845 t = Bits32 (opcode, 15, 12);
9846 t2 = Bits32 (opcode, 11, 8);
9847 n = Bits32 (opcode, 19, 16);
9848 imm32 = Bits32 (opcode, 7, 0) << 2;
9849
9850 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9851 index = BitIsSet (opcode, 24);
9852 add = BitIsSet (opcode, 23);
9853 wback = BitIsSet (opcode, 21);
9854
9855 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9856 if (wback && ((n == t) || (n == t2)))
9857 return false;
9858
9859 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9860 if (BadReg (t) || BadReg (t2) || (t == t2))
9861 return false;
9862
9863 break;
9864
9865 case eEncodingA1:
9866 //if Rn == ‘1111’ then SEE LDRD (literal);
9867 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9868 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9869 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009870 if (BitIsSet (t, 0))
9871 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009872 t2 = t + 1;
9873 n = Bits32 (opcode, 19, 16);
9874 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9875
9876 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9877 index = BitIsSet (opcode, 24);
9878 add = BitIsSet (opcode, 23);
9879 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9880
9881 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9882 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9883 return false;
9884
9885 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9886 if (wback && ((n == t) || (n == t2)))
9887 return false;
9888
9889 //if t2 == 15 then UNPREDICTABLE;
9890 if (t2 == 15)
9891 return false;
9892
9893 break;
9894
9895 default:
9896 return false;
9897 }
9898
9899 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9900 uint32_t Rn = ReadCoreReg (n, &success);
9901 if (!success)
9902 return false;
9903
9904 addr_t offset_addr;
9905 if (add)
9906 offset_addr = Rn + imm32;
9907 else
9908 offset_addr = Rn - imm32;
9909
9910 //address = if index then offset_addr else R[n];
9911 addr_t address;
9912 if (index)
9913 address = offset_addr;
9914 else
9915 address = Rn;
9916
9917 //R[t] = MemA[address,4];
9918 Register base_reg;
9919 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9920
9921 EmulateInstruction::Context context;
9922 context.type = eContextRegisterLoad;
9923 context.SetRegisterPlusOffset (base_reg, address - Rn);
9924
9925 const uint32_t addr_byte_size = GetAddressByteSize();
9926 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
9927 if (!success)
9928 return false;
9929
9930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
9931 return false;
9932
9933 //R[t2] = MemA[address+4,4];
9934
9935 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
9936 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
9937 if (!success)
9938 return false;
9939
9940 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
9941 return false;
9942
9943 //if wback then R[n] = offset_addr;
9944 if (wback)
9945 {
9946 context.type = eContextAdjustBaseRegister;
9947 context.SetAddress (offset_addr);
9948
9949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9950 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009951 }
9952 }
9953 return true;
9954}
9955
Caroline Ticed05b4902011-03-29 21:24:06 +00009956// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +00009957// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
9958// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +00009959bool
9960EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
9961{
9962#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +00009963 if ConditionPassed() then
9964 EncodingSpecificOperations();
9965 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
9966 address = if index then offset_addr else R[n];
9967 R[t] = MemA[address,4];
9968 R[t2] = MemA[address+4,4];
9969 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009970#endif
9971
Caroline Ticeeab301f2011-03-30 17:54:52 +00009972 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009973
9974 if (ConditionPassed(opcode))
9975 {
Caroline Ticeeab301f2011-03-30 17:54:52 +00009976 uint32_t t;
9977 uint32_t t2;
9978 uint32_t n;
9979 uint32_t m;
9980 bool index;
9981 bool add;
9982 bool wback;
9983
Caroline Ticed05b4902011-03-29 21:24:06 +00009984 switch (encoding)
9985 {
Caroline Ticeeab301f2011-03-30 17:54:52 +00009986 case eEncodingA1:
9987 // if Rt<0> == ‘1’ then UNPREDICTABLE;
9988 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
9989 t = Bits32 (opcode, 15, 12);
9990 if (BitIsSet (t, 0))
9991 return false;
9992 t2 = t + 1;
9993 n = Bits32 (opcode, 19, 16);
9994 m = Bits32 (opcode, 3, 0);
9995
9996 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9997 index = BitIsSet (opcode, 24);
9998 add = BitIsSet (opcode, 23);
9999 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10000
10001 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10002 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10003 return false;
10004
10005 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10006 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10007 return false;
10008
10009 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10010 if (wback && ((n == 15) || (n == t) || (n == t2)))
10011 return false;
10012
10013 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10014 if ((ArchVersion() < 6) && wback && (m == n))
10015 return false;
10016 break;
10017
10018 default:
10019 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010020 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010021
Caroline Ticeeab301f2011-03-30 17:54:52 +000010022 uint32_t Rn = ReadCoreReg (n, &success);
10023 if (!success)
10024 return false;
10025 Register base_reg;
10026 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed05b4902011-03-29 21:24:06 +000010027
Caroline Ticeeab301f2011-03-30 17:54:52 +000010028 uint32_t Rm = ReadCoreReg (m, &success);
10029 if (!success)
10030 return false;
10031 Register offset_reg;
10032 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticed05b4902011-03-29 21:24:06 +000010033
Caroline Ticeeab301f2011-03-30 17:54:52 +000010034 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10035 addr_t offset_addr;
10036 if (add)
10037 offset_addr = Rn + Rm;
10038 else
10039 offset_addr = Rn - Rm;
10040
10041 // address = if index then offset_addr else R[n];
10042 addr_t address;
10043 if (index)
10044 address = offset_addr;
10045 else
10046 address = Rn;
10047
10048 EmulateInstruction::Context context;
10049 context.type = eContextRegisterLoad;
10050 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10051
10052 // R[t] = MemA[address,4];
10053 const uint32_t addr_byte_size = GetAddressByteSize();
10054 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10055 if (!success)
10056 return false;
10057
10058 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10059 return false;
10060
10061 // R[t2] = MemA[address+4,4];
10062
10063 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10064 if (!success)
10065 return false;
10066
10067 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10068 return false;
10069
10070 // if wback then R[n] = offset_addr;
10071 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010072 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010073 context.type = eContextAdjustBaseRegister;
10074 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010075
Caroline Ticeeab301f2011-03-30 17:54:52 +000010076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10077 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010078 }
10079 }
10080 return true;
10081}
Caroline Ticed05b4902011-03-29 21:24:06 +000010082
10083// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010084// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10085// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +000010086bool
10087EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10088{
10089#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010090 if ConditionPassed() then
10091 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10092 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10093 address = if index then offset_addr else R[n];
10094 MemA[address,4] = R[t];
10095 MemA[address+4,4] = R[t2];
10096 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010097#endif
10098
Caroline Tice74467fe2011-03-30 19:02:56 +000010099 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010100
Caroline Tice74467fe2011-03-30 19:02:56 +000010101 if (ConditionPassed(opcode))
10102 {
10103 uint32_t t;
10104 uint32_t t2;
10105 uint32_t n;
10106 uint32_t imm32;
10107 bool index;
10108 bool add;
10109 bool wback;
10110
10111 switch (encoding)
10112 {
10113 case eEncodingT1:
10114 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10115 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10116 t = Bits32 (opcode, 15, 12);
10117 t2 = Bits32 (opcode, 11, 8);
10118 n = Bits32 (opcode, 19, 16);
10119 imm32 = Bits32 (opcode, 7, 0) << 2;
10120
10121 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10122 index = BitIsSet (opcode, 24);
10123 add = BitIsSet (opcode, 23);
10124 wback = BitIsSet (opcode, 21);
10125
10126 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10127 if (wback && ((n == t) || (n == t2)))
10128 return false;
10129
10130 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10131 if ((n == 15) || BadReg (t) || BadReg (t2))
10132 return false;
10133
10134 break;
10135
10136 case eEncodingA1:
10137 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10138 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10139 t = Bits32 (opcode, 15, 12);
10140 if (BitIsSet (t, 0))
10141 return false;
10142
10143 t2 = t + 1;
10144 n = Bits32 (opcode, 19, 16);
10145 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10146
10147 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10148 index = BitIsSet (opcode, 24);
10149 add = BitIsSet (opcode, 23);
10150 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10151
10152 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10153 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10154 return false;
10155
10156 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10157 if (wback && ((n == 15) || (n == t) || (n == t2)))
10158 return false;
10159
10160 // if t2 == 15 then UNPREDICTABLE;
10161 if (t2 == 15)
10162 return false;
10163
10164 break;
10165
10166 default:
10167 return false;
10168 }
10169
10170 Register base_reg;
10171 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10172
10173 uint32_t Rn = ReadCoreReg (n, &success);
10174 if (!success)
10175 return false;
10176
10177 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10178 addr_t offset_addr;
10179 if (add)
10180 offset_addr = Rn + imm32;
10181 else
10182 offset_addr = Rn - imm32;
10183
10184 //address = if index then offset_addr else R[n];
10185 addr_t address;
10186 if (index)
10187 address = offset_addr;
10188 else
10189 address = Rn;
10190
10191 //MemA[address,4] = R[t];
10192 Register data_reg;
10193 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10194
10195 uint32_t data = ReadCoreReg (t, &success);
10196 if (!success)
10197 return false;
10198
10199 EmulateInstruction::Context context;
10200 context.type = eContextRegisterStore;
10201 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10202
10203 const uint32_t addr_byte_size = GetAddressByteSize();
10204
10205 if (!MemAWrite (context, address, data, addr_byte_size))
10206 return false;
10207
10208 //MemA[address+4,4] = R[t2];
10209 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2);
10210 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10211
10212 data = ReadCoreReg (t2, &success);
10213 if (!success)
10214 return false;
10215
10216 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10217 return false;
10218
10219 //if wback then R[n] = offset_addr;
10220 if (wback)
10221 {
10222 context.type = eContextAdjustBaseRegister;
10223 context.SetAddress (offset_addr);
10224
10225 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10226 return false;
10227 }
10228 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010229 return true;
10230}
10231
10232
10233// A8.6.201 STRD (register)
10234bool
10235EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10236{
10237#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010238 if ConditionPassed() then
10239 EncodingSpecificOperations();
10240 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10241 address = if index then offset_addr else R[n];
10242 MemA[address,4] = R[t];
10243 MemA[address+4,4] = R[t2];
10244 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010245#endif
10246
Caroline Tice74467fe2011-03-30 19:02:56 +000010247 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010248
Caroline Tice74467fe2011-03-30 19:02:56 +000010249 if (ConditionPassed(opcode))
10250 {
10251 uint32_t t;
10252 uint32_t t2;
10253 uint32_t n;
10254 uint32_t m;
10255 bool index;
10256 bool add;
10257 bool wback;
10258
10259 switch (encoding)
10260 {
10261 case eEncodingA1:
10262 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10263 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10264 t = Bits32 (opcode, 15, 12);
10265 if (BitIsSet (t, 0))
10266 return false;
10267
10268 t2 = t+1;
10269 n = Bits32 (opcode, 19, 16);
10270 m = Bits32 (opcode, 3, 0);
10271
10272 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10273 index = BitIsSet (opcode, 24);
10274 add = BitIsSet (opcode, 23);
10275 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10276
10277 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10278 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10279 return false;
10280
10281 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10282 if ((t2 == 15) || (m == 15))
10283 return false;
10284
10285 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10286 if (wback && ((n == 15) || (n == t) || (n == t2)))
10287 return false;
10288
10289 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010290 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010291 return false;
10292
10293 break;
10294
10295 default:
10296 return false;
10297 }
10298
10299 Register base_reg;
10300 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10301 Register offset_reg;
10302 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10303 Register data_reg;
10304 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10305
10306 uint32_t Rn = ReadCoreReg (n, &success);
10307 if (!success)
10308 return false;
10309
10310 uint32_t Rm = ReadCoreReg (m, &success);
10311 if (!success)
10312 return false;
10313
10314 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10315 addr_t offset_addr;
10316 if (add)
10317 offset_addr = Rn + Rm;
10318 else
10319 offset_addr = Rn - Rm;
10320
10321 // address = if index then offset_addr else R[n];
10322 addr_t address;
10323 if (index)
10324 address = offset_addr;
10325 else
10326 address = Rn;
10327 // MemA[address,4] = R[t];
10328 uint32_t Rt = ReadCoreReg (t, &success);
10329 if (!success)
10330 return false;
10331
10332 EmulateInstruction::Context context;
10333 context.type = eContextRegisterStore;
10334 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10335
10336 const uint32_t addr_byte_size = GetAddressByteSize();
10337
10338 if (!MemAWrite (context, address, Rt, addr_byte_size))
10339 return false;
10340
10341 // MemA[address+4,4] = R[t2];
10342 uint32_t Rt2 = ReadCoreReg (t2, &success);
10343 if (!success)
10344 return false;
10345
10346 data_reg.num = dwarf_r0 + t2;
10347
10348 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10349
10350 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10351 return false;
10352
10353 // if wback then R[n] = offset_addr;
10354 if (wback)
10355 {
10356 context.type = eContextAdjustBaseRegister;
10357 context.SetAddress (offset_addr);
10358
10359 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10360 return false;
10361
10362 }
10363 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010364 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010365}
10366
Caroline Tice4f605582011-03-31 00:02:51 +000010367// A8.6.319 VLDM
10368// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10369// an ARM core register.
10370bool
10371EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10372{
10373#if 0
10374 if ConditionPassed() then
10375 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10376 address = if add then R[n] else R[n]-imm32;
10377 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10378 for r = 0 to regs-1
10379 if single_regs then
10380 S[d+r] = MemA[address,4]; address = address+4;
10381 else
10382 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10383 // Combine the word-aligned words in the correct order for current endianness.
10384 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10385#endif
10386
10387 bool success = false;
10388
10389 if (ConditionPassed(opcode))
10390 {
10391 bool single_regs;
10392 bool add;
10393 bool wback;
10394 uint32_t d;
10395 uint32_t n;
10396 uint32_t imm32;
10397 uint32_t regs;
10398 switch (encoding)
10399 {
10400 case eEncodingT1:
10401 case eEncodingA1:
10402 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10403 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10404 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10405 // if P == U && W == ‘1’ then UNDEFINED;
10406 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10407 return false;
10408
10409 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10410 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10411 single_regs = false;
10412 add = BitIsSet (opcode, 23);
10413 wback = BitIsSet (opcode, 21);
10414
10415 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10416 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10417 n = Bits32 (opcode, 19, 16);
10418 imm32 = Bits32 (opcode, 7, 0) << 2;
10419
10420 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10421 regs = Bits32 (opcode, 7, 0) / 2;
10422
10423 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10424 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10425 return false;
10426
10427 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10428 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10429 return false;
10430
10431 break;
10432
10433 case eEncodingT2:
10434 case eEncodingA2:
10435 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10436 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10437 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10438 // if P == U && W == ‘1’ then UNDEFINED;
10439 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10440 return false;
10441
10442 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10443 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10444 single_regs = true;
10445 add = BitIsSet (opcode, 23);
10446 wback = BitIsSet (opcode, 21);
10447 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10448 n = Bits32 (opcode, 19, 16);
10449
10450 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10451 imm32 = Bits32 (opcode, 7, 0) << 2;
10452 regs = Bits32 (opcode, 7, 0);
10453
10454 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10455 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10456 return false;
10457
10458 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10459 if ((regs == 0) || ((d + regs) > 32))
10460 return false;
10461 break;
10462
10463 default:
10464 return false;
10465 }
10466
10467 Register base_reg;
10468 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10469
10470 uint32_t Rn = ReadCoreReg (n, &success);
10471 if (!success)
10472 return false;
10473
10474 // address = if add then R[n] else R[n]-imm32;
10475 addr_t address;
10476 if (add)
10477 address = Rn;
10478 else
10479 address = Rn - imm32;
10480
10481 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10482 EmulateInstruction::Context context;
10483
10484 if (wback)
10485 {
10486 uint32_t value;
10487 if (add)
10488 value = Rn + imm32;
10489 else
10490 value = Rn - imm32;
10491
10492 context.type = eContextAdjustBaseRegister;
10493 context.SetImmediateSigned (value - Rn);
10494 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10495 return false;
10496
10497 }
10498
10499 const uint32_t addr_byte_size = GetAddressByteSize();
10500 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10501
10502 context.type = eContextRegisterLoad;
10503
10504 // for r = 0 to regs-1
10505 for (uint32_t r = 0; r < regs; r++)
10506 {
10507 if (single_regs)
10508 {
10509 // S[d+r] = MemA[address,4]; address = address+4;
10510 context.SetRegisterPlusOffset (base_reg, address - Rn);
10511
10512 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10513 if (!success)
10514 return false;
10515
10516 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10517 return false;
10518
10519 address = address + 4;
10520 }
10521 else
10522 {
10523 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10524 context.SetRegisterPlusOffset (base_reg, address - Rn);
10525 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10526 if (!success)
10527 return false;
10528
10529 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10530 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10531 if (!success)
10532 return false;
10533
10534 address = address + 8;
10535 // // Combine the word-aligned words in the correct order for current endianness.
10536 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10537 uint64_t data;
10538 if (m_byte_order == eByteOrderBig)
10539 {
10540 data = word1;
10541 data = (data << 32) | word2;
10542 }
10543 else
10544 {
10545 data = word2;
10546 data = (data << 32) | word1;
10547 }
10548
10549 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10550 return false;
10551 }
10552 }
10553 }
10554 return true;
10555}
10556
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010557EmulateInstructionARM::ARMOpcode*
10558EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000010559{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010560 static ARMOpcode
10561 g_arm_opcodes[] =
10562 {
10563 //----------------------------------------------------------------------
10564 // Prologue instructions
10565 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000010566
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010567 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000010568 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
10569 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000010570
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010571 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000010572 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
10573 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000010574 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000010575 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
10576 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
10577 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000010578
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010579 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000010580 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
10581 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000010582
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010583 // push one register
10584 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000010585 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000010586
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010587 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000010588 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
10589 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000010590
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010591 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000010592 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010593 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000010594
Caroline Tice4f605582011-03-31 00:02:51 +000010595 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
10596 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
10597 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
10598 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010599
10600 //----------------------------------------------------------------------
10601 // Supervisor Call (previously Software Interrupt)
10602 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010603 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000010604
10605 //----------------------------------------------------------------------
10606 // Branch instructions
10607 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010608 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000010609 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000010610 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
10611 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
10612 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000010613 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000010614 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000010615 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000010616 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010617
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010618 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000010619 // Data-processing instructions
10620 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000010621 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010622 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000010623 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010624 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000010625 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010626 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000010627 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010628 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000010629 // add (register-shifted register)
Caroline Tice4f605582011-03-31 00:02:51 +000010630 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000010631 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000010632 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10633 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010634 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010635 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010636 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010637 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010638 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010639 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010640 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010641 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010642 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010643 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000010644 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010645 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010646 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010647 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010648 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010649 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010650 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010651 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010652 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010653 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000010654 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010655 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000010656 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010657 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000010658 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010659 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000010660 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010661 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000010662 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000010663 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000010664 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010665 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000010666 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010667 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010668 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010669 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000010670 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010671 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010672 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010673 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000010674 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010675 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010676
Caroline Tice89c6d582011-03-29 19:53:44 +000010677 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010678 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
10679 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000010680 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010681 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010682 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010683 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010684 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010685 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000010686 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010687 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000010688 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010689 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010690 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010691 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010692 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010693 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000010694 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010695 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010696 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010697 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010698 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010699 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010700 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010701 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010702 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010703 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010704 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010705 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010706 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010707 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010708 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010709 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010710 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010711 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000010712 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000010713 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +000010714
10715 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010716 // Load instructions
10717 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010718 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
10719 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
10720 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
10721 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
10722 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
10723 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
10724 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
10725 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
10726 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
10727 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
10728 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
10729 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
10730 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
10731 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
10732 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
10733 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
10734 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
10735 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
10736 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
10737 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{most}<c> <Rn>{!}, <list>"},
Caroline Ticefa172202011-02-11 22:49:54 +000010738
10739 //----------------------------------------------------------------------
10740 // Store instructions
10741 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010742 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
10743 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
10744 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
10745 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
10746 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
10747 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
10748 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
10749 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
10750 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
10751 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strc<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
10752 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1511f502011-02-15 00:19:42 +000010753
Caroline Tice6bf65162011-03-03 17:42:58 +000010754 //----------------------------------------------------------------------
10755 // Other instructions
10756 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010757 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
10758 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
10759 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
10760 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
10761 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000010762
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010763 };
10764 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
10765
10766 for (size_t i=0; i<k_num_arm_opcodes; ++i)
10767 {
10768 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
10769 return &g_arm_opcodes[i];
10770 }
10771 return NULL;
10772}
Greg Clayton64c84432011-01-21 22:02:52 +000010773
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010774
10775EmulateInstructionARM::ARMOpcode*
10776EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +000010777{
Johnny Chenfdd179e2011-01-31 20:09:28 +000010778
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010779 static ARMOpcode
10780 g_thumb_opcodes[] =
10781 {
10782 //----------------------------------------------------------------------
10783 // Prologue instructions
10784 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000010785
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010786 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000010787 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
10788 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
10789 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000010790
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010791 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000010792 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000010793 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000010794 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000010795 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000010796 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000010797
Johnny Chen864a8e82011-02-18 00:07:39 +000010798 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000010799 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000010800
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010801 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000010802 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
10803 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
10804 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
10805 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
10806 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000010807
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010808 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000010809 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
10810 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000010811
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010812 //----------------------------------------------------------------------
10813 // Epilogue instructions
10814 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000010815
Caroline Tice4f605582011-03-31 00:02:51 +000010816 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
10817 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
10818 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
10819 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
10820 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
10821 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
10822 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010823
10824 //----------------------------------------------------------------------
10825 // Supervisor Call (previously Software Interrupt)
10826 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010827 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000010828
10829 //----------------------------------------------------------------------
10830 // If Then makes up to four following instructions conditional.
10831 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010832 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000010833
10834 //----------------------------------------------------------------------
10835 // Branch instructions
10836 //----------------------------------------------------------------------
10837 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000010838 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
10839 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
10840 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
10841 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +000010842 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000010843 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000010844 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000010845 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
10846 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000010847 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000010848 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000010849 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000010850 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000010851 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000010852 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000010853 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000010854 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000010855 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000010856 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010857
10858 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000010859 // Data-processing instructions
10860 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000010861 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010862 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000010863 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010864 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
10865 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen157b9592011-02-18 21:13:05 +000010866 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010867 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000010868 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000010869 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000010870 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000010871 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10872 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
10873 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010874 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010875 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010876 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010877 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
10878 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010879 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010880 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010881 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010882 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
10883 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010884 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010885 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000010886 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010887 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
10888 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010889 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010890 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010891 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010892 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
10893 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010894 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010895 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
10896 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010897 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010898 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000010899 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010900 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000010901 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010902 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
10903 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +000010904 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000010905 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
10906 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
10907 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
10908 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000010909 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000010910 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
10911 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
10912 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
10913 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000010914 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010915 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
10916 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000010917 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010918 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
10919 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010920 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010921 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000010922 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010923 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010924 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010925 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000010926 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010927 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
10928 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010929
Johnny Chen7c5234d2011-02-18 23:41:11 +000010930
Johnny Chen338bf542011-02-10 19:29:03 +000010931 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000010932 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000010933 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000010934 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010935 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000010936 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000010937 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000010938 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
10939 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
10940 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010941 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010942 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010943 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010944 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
10945 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010946 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010947 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010948 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010949 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
10950 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010951 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010952 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
10953 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010954 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000010955 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010956 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000010957 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000010958 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010959 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
10960 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000010961 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010962 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
10963 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010964 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010965 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
10966 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010967 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010968 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
10969 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010970 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010971 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
10972 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010973 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010974 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
10975 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010976 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010977 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010978 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000010979 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010980 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000010981 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
10982 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000010983 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000010984 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000010985 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000010986 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +000010987
Johnny Chen26863dc2011-02-09 23:43:29 +000010988 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010989 // Load instructions
10990 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000010991 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
10992 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
10993 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
10994 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
10995 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
10996 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
10997 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000010998 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000010999 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
11000 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
11001 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
11002 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
11003 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
11004 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
11005 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
11006 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
11007 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
11008 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
11009 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
11010 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
11011 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
11012 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
11013 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
11014 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
11015 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
11016 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
11017 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
11018 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
11019 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
11020 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
11021 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
11022 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
11023 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
11024 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"},
11025 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
11026 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
Caroline Ticefa172202011-02-11 22:49:54 +000011027
11028 //----------------------------------------------------------------------
11029 // Store instructions
11030 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000011031 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
11032 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
11033 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
11034 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
11035 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
11036 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
11037 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
11038 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
11039 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
11040 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
11041 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
11042 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
11043 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
11044 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
11045 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
11046 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice6bf65162011-03-03 17:42:58 +000011047
11048 //----------------------------------------------------------------------
11049 // Other instructions
11050 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000011051 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
11052 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
11053 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
11054 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
11055 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
11056 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
11057 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
11058 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
11059 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
11060 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000011061
Greg Clayton2b8e8b02011-02-01 00:49:32 +000011062 };
11063
11064 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
11065 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
11066 {
11067 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
11068 return &g_thumb_opcodes[i];
11069 }
11070 return NULL;
11071}
Greg Clayton64c84432011-01-21 22:02:52 +000011072
Greg Clayton31e2a382011-01-30 20:03:56 +000011073bool
Greg Clayton395fc332011-02-15 21:59:32 +000011074EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000011075{
11076 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000011077 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000011078 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000011079 {
Greg Clayton395fc332011-02-15 21:59:32 +000011080 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
11081 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
11082 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
11083 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
11084 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
11085 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
11086 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
11087 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
11088 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
11089 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000011090 }
11091 return m_arm_isa != 0;
11092}
11093
11094
Greg Clayton64c84432011-01-21 22:02:52 +000011095bool
11096EmulateInstructionARM::ReadInstruction ()
11097{
11098 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000011099 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000011100 if (success)
11101 {
11102 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
11103 if (success)
11104 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000011105 Context read_inst_context;
11106 read_inst_context.type = eContextReadOpcode;
11107 read_inst_context.SetNoArgs ();
11108
Greg Claytonb3448432011-03-24 21:19:54 +000011109 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000011110 {
Greg Claytonb3448432011-03-24 21:19:54 +000011111 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000011112 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000011113
11114 if (success)
11115 {
Greg Clayton7bc39082011-03-24 23:53:38 +000011116 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000011117 {
Greg Clayton7bc39082011-03-24 23:53:38 +000011118 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000011119 }
11120 else
11121 {
Greg Clayton7bc39082011-03-24 23:53:38 +000011122 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000011123 }
11124 }
11125 }
11126 else
11127 {
Greg Claytonb3448432011-03-24 21:19:54 +000011128 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000011129 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000011130 }
11131 }
11132 }
11133 if (!success)
11134 {
Greg Claytonb3448432011-03-24 21:19:54 +000011135 m_opcode_mode = eModeInvalid;
11136 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000011137 }
11138 return success;
11139}
11140
Johnny Chenee9b1f72011-02-09 01:00:31 +000011141uint32_t
11142EmulateInstructionARM::ArchVersion ()
11143{
11144 return m_arm_isa;
11145}
11146
Greg Clayton64c84432011-01-21 22:02:52 +000011147bool
Greg Clayton7bc39082011-03-24 23:53:38 +000011148EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000011149{
Greg Claytonb3448432011-03-24 21:19:54 +000011150 if (m_opcode_cpsr == 0)
Greg Clayton64c84432011-01-21 22:02:52 +000011151 return false;
11152
Greg Clayton7bc39082011-03-24 23:53:38 +000011153 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000011154
11155 if (cond == UINT32_MAX)
11156 return false;
11157
11158 bool result = false;
11159 switch (UnsignedBits(cond, 3, 1))
11160 {
Greg Claytonb3448432011-03-24 21:19:54 +000011161 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
11162 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
11163 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
11164 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
11165 case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break;
Greg Clayton64c84432011-01-21 22:02:52 +000011166 case 5:
11167 {
Greg Claytonb3448432011-03-24 21:19:54 +000011168 bool n = (m_opcode_cpsr & MASK_CPSR_N);
11169 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000011170 result = n == v;
11171 }
11172 break;
11173 case 6:
11174 {
Greg Claytonb3448432011-03-24 21:19:54 +000011175 bool n = (m_opcode_cpsr & MASK_CPSR_N);
11176 bool v = (m_opcode_cpsr & MASK_CPSR_V);
11177 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000011178 }
11179 break;
11180 case 7:
11181 result = true;
11182 break;
11183 }
11184
11185 if (cond & 1)
11186 result = !result;
11187 return result;
11188}
11189
Johnny Chen9ee056b2011-02-08 00:06:35 +000011190uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000011191EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011192{
Greg Claytonb3448432011-03-24 21:19:54 +000011193 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011194 {
11195 default:
11196 case eModeInvalid:
11197 break;
11198
11199 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000011200 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011201
11202 case eModeThumb:
11203 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
11204 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000011205 {
Greg Clayton7bc39082011-03-24 23:53:38 +000011206 const uint32_t byte_size = m_opcode.GetByteSize();
11207 if (byte_size == 2)
11208 {
11209 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
11210 return Bits32(opcode, 11, 7);
11211 }
11212 else
11213 {
11214 assert (byte_size == 4);
11215 if (Bits32(opcode, 31, 27) == 0x1e &&
11216 Bits32(opcode, 15, 14) == 0x02 &&
11217 Bits32(opcode, 12, 12) == 0x00 &&
11218 Bits32(opcode, 25, 22) <= 0x0d)
11219 {
11220 return Bits32(opcode, 25, 22);
11221 }
11222 }
11223
11224 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000011225 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011226 }
11227 return UINT32_MAX; // Return invalid value
11228}
11229
Johnny Chen9ee056b2011-02-08 00:06:35 +000011230bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000011231EmulateInstructionARM::InITBlock()
11232{
11233 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
11234}
11235
11236bool
11237EmulateInstructionARM::LastInITBlock()
11238{
11239 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
11240}
11241
Caroline Ticeb27771d2011-03-03 22:37:46 +000011242bool
11243EmulateInstructionARM::BadMode (uint32_t mode)
11244{
11245
11246 switch (mode)
11247 {
11248 case 16: return false; // '10000'
11249 case 17: return false; // '10001'
11250 case 18: return false; // '10010'
11251 case 19: return false; // '10011'
11252 case 22: return false; // '10110'
11253 case 23: return false; // '10111'
11254 case 27: return false; // '11011'
11255 case 31: return false; // '11111'
11256 default: return true;
11257 }
11258 return true;
11259}
11260
11261bool
11262EmulateInstructionARM::CurrentModeIsPrivileged ()
11263{
Greg Claytonb3448432011-03-24 21:19:54 +000011264 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000011265
11266 if (BadMode (mode))
11267 return false;
11268
11269 if (mode == 16)
11270 return false;
11271
11272 return true;
11273}
11274
11275void
11276EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
11277{
11278 bool privileged = CurrentModeIsPrivileged();
11279
11280 uint32_t tmp_cpsr = 0;
11281
Greg Claytonb3448432011-03-24 21:19:54 +000011282 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000011283
11284 if (BitIsSet (bytemask, 3))
11285 {
11286 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
11287 if (affect_execstate)
11288 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
11289 }
11290
11291 if (BitIsSet (bytemask, 2))
11292 {
11293 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
11294 }
11295
11296 if (BitIsSet (bytemask, 1))
11297 {
11298 if (affect_execstate)
11299 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
11300 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
11301 if (privileged)
11302 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
11303 }
11304
11305 if (BitIsSet (bytemask, 0))
11306 {
11307 if (privileged)
11308 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
11309 if (affect_execstate)
11310 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
11311 if (privileged)
11312 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
11313 }
11314
Greg Claytonb3448432011-03-24 21:19:54 +000011315 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000011316}
11317
11318
Johnny Chen098ae2d2011-02-12 00:50:05 +000011319bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000011320EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
11321{
11322 addr_t target;
11323
Johnny Chenee9b1f72011-02-09 01:00:31 +000011324 // Check the current instruction set.
11325 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011326 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011327 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000011328 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011329
Johnny Chen9ee056b2011-02-08 00:06:35 +000011330 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000011331 return false;
11332
11333 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011334}
11335
11336// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
11337bool
Johnny Chen668b4512011-02-15 21:08:58 +000011338EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011339{
11340 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000011341 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
11342 // we want to record it and issue a WriteRegister callback so the clients
11343 // can track the mode changes accordingly.
11344 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011345
11346 if (BitIsSet(addr, 0))
11347 {
Johnny Chen0f309db2011-02-09 19:11:32 +000011348 if (CurrentInstrSet() != eModeThumb)
11349 {
11350 SelectInstrSet(eModeThumb);
11351 cpsr_changed = true;
11352 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011353 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000011354 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011355 }
11356 else if (BitIsClear(addr, 1))
11357 {
Johnny Chen0f309db2011-02-09 19:11:32 +000011358 if (CurrentInstrSet() != eModeARM)
11359 {
11360 SelectInstrSet(eModeARM);
11361 cpsr_changed = true;
11362 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011363 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000011364 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011365 }
11366 else
11367 return false; // address<1:0> == '10' => UNPREDICTABLE
11368
Johnny Chen0f309db2011-02-09 19:11:32 +000011369 if (cpsr_changed)
11370 {
Johnny Chen558133b2011-02-09 23:59:17 +000011371 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000011372 return false;
11373 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011374 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000011375 return false;
11376
11377 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011378}
Greg Clayton64c84432011-01-21 22:02:52 +000011379
Johnny Chenee9b1f72011-02-09 01:00:31 +000011380// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
11381bool
Johnny Chen668b4512011-02-15 21:08:58 +000011382EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000011383{
11384 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000011385 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000011386 else
11387 return BranchWritePC((const Context)context, addr);
11388}
11389
Johnny Chen26863dc2011-02-09 23:43:29 +000011390// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
11391bool
Johnny Chen668b4512011-02-15 21:08:58 +000011392EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000011393{
11394 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000011395 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000011396 else
11397 return BranchWritePC((const Context)context, addr);
11398}
11399
Johnny Chenee9b1f72011-02-09 01:00:31 +000011400EmulateInstructionARM::Mode
11401EmulateInstructionARM::CurrentInstrSet ()
11402{
Greg Claytonb3448432011-03-24 21:19:54 +000011403 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011404}
11405
Greg Claytonb3448432011-03-24 21:19:54 +000011406// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000011407// ReadInstruction() is performed. This function has a side effect of updating
11408// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000011409bool
11410EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
11411{
Greg Claytonb3448432011-03-24 21:19:54 +000011412 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011413 switch (arm_or_thumb)
11414 {
11415 default:
11416 return false;
11417 eModeARM:
11418 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000011419 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011420 break;
11421 eModeThumb:
11422 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000011423 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011424 break;
11425 }
11426 return true;
11427}
11428
Johnny Chenef21b592011-02-10 01:52:38 +000011429// This function returns TRUE if the processor currently provides support for
11430// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
11431// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
11432bool
11433EmulateInstructionARM::UnalignedSupport()
11434{
11435 return (ArchVersion() >= ARMv7);
11436}
11437
Johnny Chenbf6ad172011-02-11 01:29:53 +000011438// The main addition and subtraction instructions can produce status information
11439// about both unsigned carry and signed overflow conditions. This status
11440// information can be used to synthesize multi-word additions and subtractions.
11441EmulateInstructionARM::AddWithCarryResult
11442EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
11443{
11444 uint32_t result;
11445 uint8_t carry_out;
11446 uint8_t overflow;
11447
11448 uint64_t unsigned_sum = x + y + carry_in;
11449 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
11450
11451 result = UnsignedBits(unsigned_sum, 31, 0);
11452 carry_out = (result == unsigned_sum ? 0 : 1);
11453 overflow = ((int32_t)result == signed_sum ? 0 : 1);
11454
11455 AddWithCarryResult res = { result, carry_out, overflow };
11456 return res;
11457}
11458
Johnny Chen157b9592011-02-18 21:13:05 +000011459uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000011460EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000011461{
Johnny Chene39f22d2011-02-19 01:36:13 +000011462 uint32_t reg_kind, reg_num;
11463 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000011464 {
Johnny Chene39f22d2011-02-19 01:36:13 +000011465 case SP_REG:
11466 reg_kind = eRegisterKindGeneric;
11467 reg_num = LLDB_REGNUM_GENERIC_SP;
11468 break;
11469 case LR_REG:
11470 reg_kind = eRegisterKindGeneric;
11471 reg_num = LLDB_REGNUM_GENERIC_RA;
11472 break;
11473 case PC_REG:
11474 reg_kind = eRegisterKindGeneric;
11475 reg_num = LLDB_REGNUM_GENERIC_PC;
11476 break;
11477 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000011478 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000011479 {
11480 reg_kind = eRegisterKindDWARF;
11481 reg_num = dwarf_r0 + num;
11482 }
Johnny Chen157b9592011-02-18 21:13:05 +000011483 else
Johnny Chene39f22d2011-02-19 01:36:13 +000011484 {
11485 assert(0 && "Invalid register number");
11486 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000011487 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000011488 }
11489 break;
Johnny Chen157b9592011-02-18 21:13:05 +000011490 }
Johnny Chene39f22d2011-02-19 01:36:13 +000011491
11492 // Read our register.
11493 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
11494
11495 // When executing an ARM instruction , PC reads as the address of the current
11496 // instruction plus 8.
11497 // When executing a Thumb instruction , PC reads as the address of the current
11498 // instruction plus 4.
11499 if (num == 15)
11500 {
11501 if (CurrentInstrSet() == eModeARM)
11502 val += 8;
11503 else
11504 val += 4;
11505 }
Johnny Chen157b9592011-02-18 21:13:05 +000011506
11507 return val;
11508}
11509
Johnny Chenca67d1c2011-02-17 01:35:27 +000011510// Write the result to the ARM core register Rd, and optionally update the
11511// condition flags based on the result.
11512//
11513// This helper method tries to encapsulate the following pseudocode from the
11514// ARM Architecture Reference Manual:
11515//
11516// if d == 15 then // Can only occur for encoding A1
11517// ALUWritePC(result); // setflags is always FALSE here
11518// else
11519// R[d] = result;
11520// if setflags then
11521// APSR.N = result<31>;
11522// APSR.Z = IsZeroBit(result);
11523// APSR.C = carry;
11524// // APSR.V unchanged
11525//
11526// In the above case, the API client does not pass in the overflow arg, which
11527// defaults to ~0u.
11528bool
Johnny Chen10530c22011-02-17 22:37:12 +000011529EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
11530 const uint32_t result,
11531 const uint32_t Rd,
11532 bool setflags,
11533 const uint32_t carry,
11534 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000011535{
11536 if (Rd == 15)
11537 {
11538 if (!ALUWritePC (context, result))
11539 return false;
11540 }
11541 else
11542 {
Johnny Chena695f952011-02-23 21:24:25 +000011543 uint32_t reg_kind, reg_num;
11544 switch (Rd)
11545 {
11546 case SP_REG:
11547 reg_kind = eRegisterKindGeneric;
11548 reg_num = LLDB_REGNUM_GENERIC_SP;
11549 break;
11550 case LR_REG:
11551 reg_kind = eRegisterKindGeneric;
11552 reg_num = LLDB_REGNUM_GENERIC_RA;
11553 break;
11554 default:
11555 reg_kind = eRegisterKindDWARF;
11556 reg_num = dwarf_r0 + Rd;
11557 }
11558 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000011559 return false;
11560 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000011561 return WriteFlags (context, result, carry, overflow);
11562 }
11563 return true;
11564}
11565
11566// This helper method tries to encapsulate the following pseudocode from the
11567// ARM Architecture Reference Manual:
11568//
11569// APSR.N = result<31>;
11570// APSR.Z = IsZeroBit(result);
11571// APSR.C = carry;
11572// APSR.V = overflow
11573//
11574// Default arguments can be specified for carry and overflow parameters, which means
11575// not to update the respective flags.
11576bool
11577EmulateInstructionARM::WriteFlags (Context &context,
11578 const uint32_t result,
11579 const uint32_t carry,
11580 const uint32_t overflow)
11581{
Greg Claytonb3448432011-03-24 21:19:54 +000011582 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000011583 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
11584 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000011585 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000011586 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000011587 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000011588 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000011589 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000011590 {
11591 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
11592 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000011593 }
11594 return true;
11595}
11596
Greg Clayton64c84432011-01-21 22:02:52 +000011597bool
11598EmulateInstructionARM::EvaluateInstruction ()
11599{
Johnny Chenc315f862011-02-05 00:46:10 +000011600 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000011601 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000011602 m_it_session.ITAdvance();
11603
Greg Clayton64c84432011-01-21 22:02:52 +000011604 return false;
11605}