blob: 61b9a964c15b98da31126411483a6b5acafa4951 [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)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000133#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000134#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000135
Johnny Chen0e00af22011-02-10 19:40:42 +0000136//----------------------------------------------------------------------
137//
138// EmulateInstructionARM implementation
139//
140//----------------------------------------------------------------------
141
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142void
143EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000146
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000147void
148EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000149{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000150}
151
Caroline Ticefa172202011-02-11 22:49:54 +0000152// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
153bool
154EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
155{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000156 EmulateInstruction::Context context;
157 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
158 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000159
160 uint32_t random_data = rand ();
161 const uint32_t addr_byte_size = GetAddressByteSize();
162
Caroline Ticecc96eb52011-02-17 19:20:40 +0000163 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000164 return false;
165
166 return true;
167}
168
Caroline Tice713c2662011-02-11 17:59:55 +0000169// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
170bool
171EmulateInstructionARM::WriteBits32Unknown (int n)
172{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000173 EmulateInstruction::Context context;
174 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
175 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000176
Johnny Chen62ff6f52011-02-11 18:11:22 +0000177 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
179
180 if (!success)
181 return false;
182
183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
184 return false;
185
186 return true;
187}
188
Johnny Chen08c25e82011-01-31 18:02:28 +0000189// Push Multiple Registers stores multiple registers to the stack, storing to
190// consecutive memory locations ending just below the address in SP, and updates
191// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000192bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000193EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000194{
195#if 0
196 // ARM pseudo code...
197 if (ConditionPassed())
198 {
199 EncodingSpecificOperations();
200 NullCheckIfThumbEE(13);
201 address = SP - 4*BitCount(registers);
202
203 for (i = 0 to 14)
204 {
205 if (registers<i> == ’1’)
206 {
207 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
208 MemA[address,4] = bits(32) UNKNOWN;
209 else
210 MemA[address,4] = R[i];
211 address = address + 4;
212 }
213 }
214
215 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
216 MemA[address,4] = PCStoreValue();
217
218 SP = SP - 4*BitCount(registers);
219 }
220#endif
221
222 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000223 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000224 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000226 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000227 if (!success)
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000230 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000235 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000236 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // if BitCount(registers) < 1 then UNPREDICTABLE;
238 if (BitCount(registers) < 1)
239 return false;
240 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000241 case eEncodingT2:
242 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BitCount(registers) < 2 then UNPREDICTABLE;
245 if (BitCount(registers) < 2)
246 return false;
247 break;
248 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000249 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000255 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000257 // Instead of return false, let's handle the following case as well,
258 // which amounts to pushing one reg onto the full descending stacks.
259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000260 break;
261 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000262 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000268 default:
269 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 }
Johnny Chence1ca772011-01-25 01:13:00 +0000271 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000272 addr_t addr = sp - sp_offset;
273 uint32_t i;
274
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000275 EmulateInstruction::Context context;
276 context.type = EmulateInstruction::eContextPushRegisterOnStack;
277 Register dwarf_reg;
278 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000279 Register sp_reg;
280 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000281 for (i=0; i<15; ++i)
282 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000283 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000284 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000285 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000286 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000287 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000288 if (!success)
289 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000290 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000291 return false;
292 addr += addr_byte_size;
293 }
294 }
295
Johnny Chen7c1bf922011-02-08 23:49:37 +0000296 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000297 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000298 dwarf_reg.num = dwarf_pc;
299 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000300 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000301 if (!success)
302 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000303 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000304 return false;
305 }
306
307 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000308 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000309
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000310 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000311 return false;
312 }
313 return true;
314}
315
Johnny Chenef85e912011-01-31 23:07:40 +0000316// Pop Multiple Registers loads multiple registers from the stack, loading from
317// consecutive memory locations staring at the address in SP, and updates
318// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000319bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000320EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000321{
322#if 0
323 // ARM pseudo code...
324 if (ConditionPassed())
325 {
326 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
327 address = SP;
328 for i = 0 to 14
329 if registers<i> == ‘1’ then
330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
331 if registers<15> == ‘1’ then
332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
336 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
337 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
338 }
339#endif
340
341 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000342
Greg Clayton7bc39082011-03-24 23:53:38 +0000343 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000344 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000345 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000346 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349 uint32_t registers = 0;
350 uint32_t Rt; // the destination register
351 switch (encoding) {
352 case eEncodingT1:
353 registers = Bits32(opcode, 7, 0);
354 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000355 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000356 registers |= (1u << 15);
357 // if BitCount(registers) < 1 then UNPREDICTABLE;
358 if (BitCount(registers) < 1)
359 return false;
360 break;
361 case eEncodingT2:
362 // Ignore bit 13.
363 registers = Bits32(opcode, 15, 0) & ~0x2000;
364 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000365 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000366 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000367 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
368 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
369 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000370 break;
371 case eEncodingT3:
372 Rt = Bits32(opcode, 15, 12);
373 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 if (Rt == 13)
375 return false;
376 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000377 return false;
378 registers = (1u << Rt);
379 break;
380 case eEncodingA1:
381 registers = Bits32(opcode, 15, 0);
382 // Instead of return false, let's handle the following case as well,
383 // which amounts to popping one reg from the full descending stacks.
384 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
385
386 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000387 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000388 return false;
389 break;
390 case eEncodingA2:
391 Rt = Bits32(opcode, 15, 12);
392 // if t == 13 then UNPREDICTABLE;
393 if (Rt == dwarf_sp)
394 return false;
395 registers = (1u << Rt);
396 break;
397 default:
398 return false;
399 }
400 addr_t sp_offset = addr_byte_size * BitCount (registers);
401 addr_t addr = sp;
402 uint32_t i, data;
403
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000404 EmulateInstruction::Context context;
405 context.type = EmulateInstruction::eContextPopRegisterOffStack;
406 Register dwarf_reg;
407 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000408 Register sp_reg;
409 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000410 for (i=0; i<15; ++i)
411 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000412 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000413 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000414 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000415 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000416 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000417 if (!success)
418 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000419 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000420 return false;
421 addr += addr_byte_size;
422 }
423 }
424
Johnny Chen7c1bf922011-02-08 23:49:37 +0000425 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000426 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000427 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000428 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000429 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000430 if (!success)
431 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000432 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000433 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000434 return false;
435 addr += addr_byte_size;
436 }
437
438 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000439 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000440
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000441 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000442 return false;
443 }
444 return true;
445}
446
Johnny Chen5b442b72011-01-27 19:34:30 +0000447// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000448// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000449bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000450EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000451{
452#if 0
453 // ARM pseudo code...
454 if (ConditionPassed())
455 {
456 EncodingSpecificOperations();
457 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
458 if d == 15 then
459 ALUWritePC(result); // setflags is always FALSE here
460 else
461 R[d] = result;
462 if setflags then
463 APSR.N = result<31>;
464 APSR.Z = IsZeroBit(result);
465 APSR.C = carry;
466 APSR.V = overflow;
467 }
468#endif
469
470 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000471
Greg Clayton7bc39082011-03-24 23:53:38 +0000472 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000473 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000474 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477 uint32_t Rd; // the destination register
478 uint32_t imm32;
479 switch (encoding) {
480 case eEncodingT1:
481 Rd = 7;
482 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
483 break;
484 case eEncodingA1:
485 Rd = Bits32(opcode, 15, 12);
486 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
487 break;
488 default:
489 return false;
490 }
491 addr_t sp_offset = imm32;
492 addr_t addr = sp + sp_offset; // a pointer to the stack area
493
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000494 EmulateInstruction::Context context;
495 context.type = EmulateInstruction::eContextRegisterPlusOffset;
496 Register sp_reg;
497 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
498 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000499
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501 return false;
502 }
503 return true;
504}
505
Johnny Chen2ccad832011-01-28 19:57:25 +0000506// Set r7 or ip to the current stack pointer.
507// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000509EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000510{
511#if 0
512 // ARM pseudo code...
513 if (ConditionPassed())
514 {
515 EncodingSpecificOperations();
516 result = R[m];
517 if d == 15 then
518 ALUWritePC(result); // setflags is always FALSE here
519 else
520 R[d] = result;
521 if setflags then
522 APSR.N = result<31>;
523 APSR.Z = IsZeroBit(result);
524 // APSR.C unchanged
525 // APSR.V unchanged
526 }
527#endif
528
529 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000530
Greg Clayton7bc39082011-03-24 23:53:38 +0000531 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000532 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000533 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000534 if (!success)
535 return false;
536 uint32_t Rd; // the destination register
537 switch (encoding) {
538 case eEncodingT1:
539 Rd = 7;
540 break;
541 case eEncodingA1:
542 Rd = 12;
543 break;
544 default:
545 return false;
546 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000547
548 EmulateInstruction::Context context;
549 context.type = EmulateInstruction::eContextRegisterPlusOffset;
550 Register sp_reg;
551 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
552 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen1c13b622011-01-29 00:11:15 +0000560// Move from high register (r8-r15) to low register (r0-r7).
561// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000563EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000564{
Greg Clayton7bc39082011-03-24 23:53:38 +0000565 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000566}
567
568// Move from register to register.
569// MOV (register)
570bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000571EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000572{
Johnny Chen1c13b622011-01-29 00:11:15 +0000573#if 0
574 // ARM pseudo code...
575 if (ConditionPassed())
576 {
577 EncodingSpecificOperations();
578 result = R[m];
579 if d == 15 then
580 ALUWritePC(result); // setflags is always FALSE here
581 else
582 R[d] = result;
583 if setflags then
584 APSR.N = result<31>;
585 APSR.Z = IsZeroBit(result);
586 // APSR.C unchanged
587 // APSR.V unchanged
588 }
589#endif
590
591 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000592
Greg Clayton7bc39082011-03-24 23:53:38 +0000593 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000594 {
595 uint32_t Rm; // the source register
596 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000597 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000598 switch (encoding) {
599 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000600 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000602 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000603 if (Rd == 15 && InITBlock() && !LastInITBlock())
604 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000605 break;
606 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000607 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000608 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000609 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000610 if (InITBlock())
611 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000612 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000613 case eEncodingT3:
614 Rd = Bits32(opcode, 11, 8);
615 Rm = Bits32(opcode, 3, 0);
616 setflags = BitIsSet(opcode, 20);
617 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
618 if (setflags && (BadReg(Rd) || BadReg(Rm)))
619 return false;
620 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
621 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
622 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000623 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000624 case eEncodingA1:
625 Rd = Bits32(opcode, 15, 12);
626 Rm = Bits32(opcode, 3, 0);
627 setflags = BitIsSet(opcode, 20);
628 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
629 // TODO: Emulate SUBS PC, LR and related instructions.
630 if (Rd == 15 && setflags)
631 return false;
632 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000633 default:
634 return false;
635 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000636 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000637 if (!success)
638 return false;
639
640 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000641 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000642 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000643 Register dwarf_reg;
644 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000645 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000646
Johnny Chen10530c22011-02-17 22:37:12 +0000647 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000648 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 }
650 return true;
651}
652
Johnny Chen357c30f2011-02-14 22:04:25 +0000653// Move (immediate) writes an immediate value to the destination register. It
654// can optionally update the condition flags based on the value.
655// MOV (immediate)
656bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000657EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000658{
659#if 0
660 // ARM pseudo code...
661 if (ConditionPassed())
662 {
663 EncodingSpecificOperations();
664 result = imm32;
665 if d == 15 then // Can only occur for ARM encoding
666 ALUWritePC(result); // setflags is always FALSE here
667 else
668 R[d] = result;
669 if setflags then
670 APSR.N = result<31>;
671 APSR.Z = IsZeroBit(result);
672 APSR.C = carry;
673 // APSR.V unchanged
674 }
675#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000676
Greg Clayton7bc39082011-03-24 23:53:38 +0000677 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000678 {
679 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000680 uint32_t imm32; // the immediate value to be written to Rd
681 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
682 bool setflags;
683 switch (encoding) {
684 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000685 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000686 setflags = !InITBlock();
687 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000688 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000689 break;
690 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000691 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000692 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000693 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000694 if (BadReg(Rd))
695 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000696 break;
697 default:
698 return false;
699 }
700 uint32_t result = imm32;
701
702 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000703 EmulateInstruction::Context context;
704 context.type = EmulateInstruction::eContextImmediate;
705 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000706
Johnny Chen10530c22011-02-17 22:37:12 +0000707 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000708 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000709 }
710 return true;
711}
712
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000713// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
714// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
715// unsigned values.
716//
717// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
718// limited to only a few forms of the instruction.
719bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000720EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000721{
722#if 0
723 if ConditionPassed() then
724 EncodingSpecificOperations();
725 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
726 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
727 result = operand1 * operand2;
728 R[d] = result<31:0>;
729 if setflags then
730 APSR.N = result<31>;
731 APSR.Z = IsZeroBit(result);
732 if ArchVersion() == 4 then
733 APSR.C = bit UNKNOWN;
734 // else APSR.C unchanged
735 // APSR.V always unchanged
736#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000737
Greg Clayton7bc39082011-03-24 23:53:38 +0000738 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000739 {
740 uint32_t d;
741 uint32_t n;
742 uint32_t m;
743 bool setflags;
744
745 // EncodingSpecificOperations();
746 switch (encoding)
747 {
748 case eEncodingT1:
749 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
750 d = Bits32 (opcode, 2, 0);
751 n = Bits32 (opcode, 5, 3);
752 m = Bits32 (opcode, 2, 0);
753 setflags = !InITBlock();
754
755 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
756 if ((ArchVersion() < ARMv6) && (d == n))
757 return false;
758
759 break;
760
761 case eEncodingT2:
762 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
763 d = Bits32 (opcode, 11, 8);
764 n = Bits32 (opcode, 19, 16);
765 m = Bits32 (opcode, 3, 0);
766 setflags = false;
767
768 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
769 if (BadReg (d) || BadReg (n) || BadReg (m))
770 return false;
771
772 break;
773
774 case eEncodingA1:
775 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
776 d = Bits32 (opcode, 19, 16);
777 n = Bits32 (opcode, 3, 0);
778 m = Bits32 (opcode, 11, 8);
779 setflags = BitIsSet (opcode, 20);
780
781 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
782 if ((d == 15) || (n == 15) || (m == 15))
783 return false;
784
785 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
786 if ((ArchVersion() < ARMv6) && (d == n))
787 return false;
788
789 break;
790
791 default:
792 return false;
793 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000794
795 bool success = false;
796
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000797 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
798 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
799 if (!success)
800 return false;
801
802 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
803 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
804 if (!success)
805 return false;
806
807 // result = operand1 * operand2;
808 uint64_t result = operand1 * operand2;
809
810 // R[d] = result<31:0>;
811 Register op1_reg;
812 Register op2_reg;
813 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
814 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
815
816 EmulateInstruction::Context context;
817 context.type = eContextMultiplication;
818 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
819
820 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
821 return false;
822
823 // if setflags then
824 if (setflags)
825 {
826 // APSR.N = result<31>;
827 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000828 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000829 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
830 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000831 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000832 {
833 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
834 return false;
835 }
836
837 // if ArchVersion() == 4 then
838 // APSR.C = bit UNKNOWN;
839 }
840 }
841 return true;
842}
843
Johnny Chend642a6a2011-02-22 01:01:03 +0000844// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
845// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000846bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000847EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000848{
849#if 0
850 // ARM pseudo code...
851 if (ConditionPassed())
852 {
853 EncodingSpecificOperations();
854 result = NOT(imm32);
855 if d == 15 then // Can only occur for ARM encoding
856 ALUWritePC(result); // setflags is always FALSE here
857 else
858 R[d] = result;
859 if setflags then
860 APSR.N = result<31>;
861 APSR.Z = IsZeroBit(result);
862 APSR.C = carry;
863 // APSR.V unchanged
864 }
865#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000866
Greg Clayton7bc39082011-03-24 23:53:38 +0000867 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000868 {
869 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000870 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
871 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000872 bool setflags;
873 switch (encoding) {
874 case eEncodingT1:
875 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000876 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000877 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000878 break;
879 case eEncodingA1:
880 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000881 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000882 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
883 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
884 // TODO: Emulate SUBS PC, LR and related instructions.
885 if (Rd == 15 && setflags)
886 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000887 break;
888 default:
889 return false;
890 }
891 uint32_t result = ~imm32;
892
893 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000894 EmulateInstruction::Context context;
895 context.type = EmulateInstruction::eContextImmediate;
896 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000897
Johnny Chen10530c22011-02-17 22:37:12 +0000898 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000899 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000900 }
901 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000902}
903
Johnny Chend642a6a2011-02-22 01:01:03 +0000904// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
905// It can optionally update the condition flags based on the result.
906bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000907EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +0000908{
909#if 0
910 // ARM pseudo code...
911 if (ConditionPassed())
912 {
913 EncodingSpecificOperations();
914 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
915 result = NOT(shifted);
916 if d == 15 then // Can only occur for ARM encoding
917 ALUWritePC(result); // setflags is always FALSE here
918 else
919 R[d] = result;
920 if setflags then
921 APSR.N = result<31>;
922 APSR.Z = IsZeroBit(result);
923 APSR.C = carry;
924 // APSR.V unchanged
925 }
926#endif
927
Greg Clayton7bc39082011-03-24 23:53:38 +0000928 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +0000929 {
930 uint32_t Rm; // the source register
931 uint32_t Rd; // the destination register
932 ARM_ShifterType shift_t;
933 uint32_t shift_n; // the shift applied to the value read from Rm
934 bool setflags;
935 uint32_t carry; // the carry bit after the shift operation
936 switch (encoding) {
937 case eEncodingT1:
938 Rd = Bits32(opcode, 2, 0);
939 Rm = Bits32(opcode, 5, 3);
940 setflags = !InITBlock();
941 shift_t = SRType_LSL;
942 shift_n = 0;
943 if (InITBlock())
944 return false;
945 break;
946 case eEncodingT2:
947 Rd = Bits32(opcode, 11, 8);
948 Rm = Bits32(opcode, 3, 0);
949 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000950 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000951 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000952 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000953 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000954 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000955 case eEncodingA1:
956 Rd = Bits32(opcode, 15, 12);
957 Rm = Bits32(opcode, 3, 0);
958 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000959 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000960 break;
961 default:
962 return false;
963 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000964 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +0000965 uint32_t value = ReadCoreReg(Rm, &success);
966 if (!success)
967 return false;
968
969 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
970 uint32_t result = ~shifted;
971
972 // The context specifies that an immediate is to be moved into Rd.
973 EmulateInstruction::Context context;
974 context.type = EmulateInstruction::eContextImmediate;
975 context.SetNoArgs ();
976
977 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
978 return false;
979 }
980 return true;
981}
982
Johnny Chen788e0552011-01-27 22:52:23 +0000983// PC relative immediate load into register, possibly followed by ADD (SP plus register).
984// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000985bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000986EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000987{
988#if 0
989 // ARM pseudo code...
990 if (ConditionPassed())
991 {
992 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
993 base = Align(PC,4);
994 address = if add then (base + imm32) else (base - imm32);
995 data = MemU[address,4];
996 if t == 15 then
997 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
998 elsif UnalignedSupport() || address<1:0> = ‘00’ then
999 R[t] = data;
1000 else // Can only apply before ARMv7
1001 if CurrentInstrSet() == InstrSet_ARM then
1002 R[t] = ROR(data, 8*UInt(address<1:0>));
1003 else
1004 R[t] = bits(32) UNKNOWN;
1005 }
1006#endif
1007
Greg Clayton7bc39082011-03-24 23:53:38 +00001008 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001009 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001010 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001011 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001012 if (!success)
1013 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001014
1015 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001016 EmulateInstruction::Context context;
1017 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1018 Register pc_reg;
1019 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1020 context.SetRegisterPlusOffset (pc_reg, 0);
1021
Johnny Chenc9de9102011-02-11 19:12:30 +00001022 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001023 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001024 bool add; // +imm32 or -imm32?
1025 addr_t base; // the base address
1026 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001027 uint32_t data; // the literal data value from the PC relative load
1028 switch (encoding) {
1029 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001030 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001031 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001032 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001033 break;
1034 case eEncodingT2:
1035 Rt = Bits32(opcode, 15, 12);
1036 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1037 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001038 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001039 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001040 break;
1041 default:
1042 return false;
1043 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001044
Johnny Chene39f22d2011-02-19 01:36:13 +00001045 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001046 if (add)
1047 address = base + imm32;
1048 else
1049 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001050
1051 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001052 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001053 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001054 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001055
1056 if (Rt == 15)
1057 {
1058 if (Bits32(address, 1, 0) == 0)
1059 {
1060 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001061 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001062 return false;
1063 }
1064 else
1065 return false;
1066 }
1067 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1068 {
1069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1070 return false;
1071 }
1072 else // We don't handle ARM for now.
1073 return false;
1074
Johnny Chen788e0552011-01-27 22:52:23 +00001075 }
1076 return true;
1077}
1078
Johnny Chen5b442b72011-01-27 19:34:30 +00001079// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001080// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001081bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001082EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001083{
1084#if 0
1085 // ARM pseudo code...
1086 if (ConditionPassed())
1087 {
1088 EncodingSpecificOperations();
1089 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1090 if d == 15 then // Can only occur for ARM encoding
1091 ALUWritePC(result); // setflags is always FALSE here
1092 else
1093 R[d] = result;
1094 if setflags then
1095 APSR.N = result<31>;
1096 APSR.Z = IsZeroBit(result);
1097 APSR.C = carry;
1098 APSR.V = overflow;
1099 }
1100#endif
1101
1102 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001103
Greg Clayton7bc39082011-03-24 23:53:38 +00001104 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001105 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001106 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001107 if (!success)
1108 return false;
1109 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001110 uint32_t d;
1111 bool setflags;
1112 switch (encoding)
1113 {
1114 case eEncodingT1:
1115 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:’00’, 32);
1116 d = Bits32 (opcode, 10, 8);
1117 setflags = false;
1118 imm32 = (Bits32 (opcode, 7, 0) << 2);
1119
1120 break;
1121
1122 case eEncodingT2:
1123 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:’00’, 32);
1124 d = 13;
1125 setflags = false;
1126 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1127
1128 break;
1129
1130 default:
1131 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001132 }
1133 addr_t sp_offset = imm32;
1134 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1135
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001136 EmulateInstruction::Context context;
1137 context.type = EmulateInstruction::eContextAdjustStackPointer;
1138 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001139
Caroline Ticee2212882011-03-22 22:38:28 +00001140 if (d == 15)
1141 {
1142 if (!ALUWritePC (context, addr))
1143 return false;
1144 }
1145 else
1146 {
1147 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1148 return false;
1149 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001150 }
1151 return true;
1152}
1153
1154// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001155// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001156bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001157EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001158{
1159#if 0
1160 // ARM pseudo code...
1161 if (ConditionPassed())
1162 {
1163 EncodingSpecificOperations();
1164 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1165 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1166 if d == 15 then
1167 ALUWritePC(result); // setflags is always FALSE here
1168 else
1169 R[d] = result;
1170 if setflags then
1171 APSR.N = result<31>;
1172 APSR.Z = IsZeroBit(result);
1173 APSR.C = carry;
1174 APSR.V = overflow;
1175 }
1176#endif
1177
1178 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001179
Greg Clayton7bc39082011-03-24 23:53:38 +00001180 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001181 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001182 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001183 if (!success)
1184 return false;
1185 uint32_t Rm; // the second operand
1186 switch (encoding) {
1187 case eEncodingT2:
1188 Rm = Bits32(opcode, 6, 3);
1189 break;
1190 default:
1191 return false;
1192 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001193 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001194 if (!success)
1195 return false;
1196
1197 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1198
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001199 EmulateInstruction::Context context;
1200 context.type = EmulateInstruction::eContextAdjustStackPointer;
1201 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001202
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001203 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001204 return false;
1205 }
1206 return true;
1207}
1208
Johnny Chen9b8d7832011-02-02 01:13:56 +00001209// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1210// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1211// from Thumb to ARM.
1212// BLX (immediate)
1213bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001214EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001215{
1216#if 0
1217 // ARM pseudo code...
1218 if (ConditionPassed())
1219 {
1220 EncodingSpecificOperations();
1221 if CurrentInstrSet() == InstrSet_ARM then
1222 LR = PC - 4;
1223 else
1224 LR = PC<31:1> : '1';
1225 if targetInstrSet == InstrSet_ARM then
1226 targetAddress = Align(PC,4) + imm32;
1227 else
1228 targetAddress = PC + imm32;
1229 SelectInstrSet(targetInstrSet);
1230 BranchWritePC(targetAddress);
1231 }
1232#endif
1233
Greg Clayton7bc39082011-03-24 23:53:38 +00001234 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001235
Greg Clayton7bc39082011-03-24 23:53:38 +00001236 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001237 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001238 EmulateInstruction::Context context;
1239 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001240 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001241 if (!success)
1242 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001243 addr_t lr; // next instruction address
1244 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001245 int32_t imm32; // PC-relative offset
1246 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001247 case eEncodingT1:
1248 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001249 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001250 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001251 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001252 uint32_t J1 = Bit32(opcode, 13);
1253 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001254 uint32_t imm11 = Bits32(opcode, 10, 0);
1255 uint32_t I1 = !(J1 ^ S);
1256 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001257 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001258 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001259 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001260 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001261 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001262 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001263 break;
1264 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001265 case eEncodingT2:
1266 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001267 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001268 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001269 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001270 uint32_t J1 = Bit32(opcode, 13);
1271 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001272 uint32_t imm10L = Bits32(opcode, 10, 1);
1273 uint32_t I1 = !(J1 ^ S);
1274 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001275 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001276 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001277 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001278 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001279 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001280 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001281 break;
1282 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001283 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001284 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001285 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001286 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001287 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001288 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001290 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001292 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001293 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001294 break;
1295 default:
1296 return false;
1297 }
1298 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1299 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001300 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001301 return false;
1302 }
1303 return true;
1304}
1305
1306// Branch with Link and Exchange (register) calls a subroutine at an address and
1307// instruction set specified by a register.
1308// BLX (register)
1309bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001310EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311{
1312#if 0
1313 // ARM pseudo code...
1314 if (ConditionPassed())
1315 {
1316 EncodingSpecificOperations();
1317 target = R[m];
1318 if CurrentInstrSet() == InstrSet_ARM then
1319 next_instr_addr = PC - 4;
1320 LR = next_instr_addr;
1321 else
1322 next_instr_addr = PC - 2;
1323 LR = next_instr_addr<31:1> : ‘1’;
1324 BXWritePC(target);
1325 }
1326#endif
1327
1328 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001329
Greg Clayton7bc39082011-03-24 23:53:38 +00001330 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001331 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001332 EmulateInstruction::Context context;
1333 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001334 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001335 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001336 if (!success)
1337 return false;
1338 uint32_t Rm; // the register with the target address
1339 switch (encoding) {
1340 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001341 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001342 Rm = Bits32(opcode, 6, 3);
1343 // if m == 15 then UNPREDICTABLE;
1344 if (Rm == 15)
1345 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001346 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001347 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001348 break;
1349 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001350 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001351 Rm = Bits32(opcode, 3, 0);
1352 // if m == 15 then UNPREDICTABLE;
1353 if (Rm == 15)
1354 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001355 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 default:
1357 return false;
1358 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001359 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001360 if (!success)
1361 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001362 Register dwarf_reg;
1363 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1364 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001365 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1366 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001367 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001368 return false;
1369 }
1370 return true;
1371}
1372
Johnny Chenab3b3512011-02-12 00:10:51 +00001373// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001374bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001375EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001376{
1377#if 0
1378 // ARM pseudo code...
1379 if (ConditionPassed())
1380 {
1381 EncodingSpecificOperations();
1382 BXWritePC(R[m]);
1383 }
1384#endif
1385
Greg Clayton7bc39082011-03-24 23:53:38 +00001386 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001387 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001388 EmulateInstruction::Context context;
1389 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001390 uint32_t Rm; // the register with the target address
1391 switch (encoding) {
1392 case eEncodingT1:
1393 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001394 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001395 return false;
1396 break;
1397 case eEncodingA1:
1398 Rm = Bits32(opcode, 3, 0);
1399 break;
1400 default:
1401 return false;
1402 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001403 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001404 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001405 if (!success)
1406 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001407
1408 Register dwarf_reg;
1409 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001410 context.SetRegister (dwarf_reg);
1411 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001412 return false;
1413 }
1414 return true;
1415}
1416
Johnny Chen59e6ab72011-02-24 21:01:20 +00001417// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1418// address and instruction set specified by a register as though it were a BX instruction.
1419//
1420// TODO: Emulate Jazelle architecture?
1421// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1422bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001423EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001424{
1425#if 0
1426 // ARM pseudo code...
1427 if (ConditionPassed())
1428 {
1429 EncodingSpecificOperations();
1430 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1431 BXWritePC(R[m]);
1432 else
1433 if JazelleAcceptsExecution() then
1434 SwitchToJazelleExecution();
1435 else
1436 SUBARCHITECTURE_DEFINED handler call;
1437 }
1438#endif
1439
Greg Clayton7bc39082011-03-24 23:53:38 +00001440 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001441 {
1442 EmulateInstruction::Context context;
1443 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1444 uint32_t Rm; // the register with the target address
1445 switch (encoding) {
1446 case eEncodingT1:
1447 Rm = Bits32(opcode, 19, 16);
1448 if (BadReg(Rm))
1449 return false;
1450 if (InITBlock() && !LastInITBlock())
1451 return false;
1452 break;
1453 case eEncodingA1:
1454 Rm = Bits32(opcode, 3, 0);
1455 if (Rm == 15)
1456 return false;
1457 break;
1458 default:
1459 return false;
1460 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001461 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001462 addr_t target = ReadCoreReg (Rm, &success);
1463 if (!success)
1464 return false;
1465
1466 Register dwarf_reg;
1467 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1468 context.SetRegister (dwarf_reg);
1469 if (!BXWritePC(context, target))
1470 return false;
1471 }
1472 return true;
1473}
1474
Johnny Chen0d0148e2011-01-28 02:26:08 +00001475// Set r7 to point to some ip offset.
1476// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001477bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001478EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001479{
1480#if 0
1481 // ARM pseudo code...
1482 if (ConditionPassed())
1483 {
1484 EncodingSpecificOperations();
1485 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1486 if d == 15 then // Can only occur for ARM encoding
1487 ALUWritePC(result); // setflags is always FALSE here
1488 else
1489 R[d] = result;
1490 if setflags then
1491 APSR.N = result<31>;
1492 APSR.Z = IsZeroBit(result);
1493 APSR.C = carry;
1494 APSR.V = overflow;
1495 }
1496#endif
1497
Greg Clayton7bc39082011-03-24 23:53:38 +00001498 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001499 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001500 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001501 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001502 if (!success)
1503 return false;
1504 uint32_t imm32;
1505 switch (encoding) {
1506 case eEncodingA1:
1507 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1508 break;
1509 default:
1510 return false;
1511 }
1512 addr_t ip_offset = imm32;
1513 addr_t addr = ip - ip_offset; // the adjusted ip value
1514
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001515 EmulateInstruction::Context context;
1516 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1517 Register dwarf_reg;
1518 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1519 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001522 return false;
1523 }
1524 return true;
1525}
1526
1527// Set ip to point to some stack offset.
1528// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001529bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001530EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001531{
1532#if 0
1533 // ARM pseudo code...
1534 if (ConditionPassed())
1535 {
1536 EncodingSpecificOperations();
1537 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1538 if d == 15 then // Can only occur for ARM encoding
1539 ALUWritePC(result); // setflags is always FALSE here
1540 else
1541 R[d] = result;
1542 if setflags then
1543 APSR.N = result<31>;
1544 APSR.Z = IsZeroBit(result);
1545 APSR.C = carry;
1546 APSR.V = overflow;
1547 }
1548#endif
1549
Greg Clayton7bc39082011-03-24 23:53:38 +00001550 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001551 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001552 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001553 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001554 if (!success)
1555 return false;
1556 uint32_t imm32;
1557 switch (encoding) {
1558 case eEncodingA1:
1559 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1560 break;
1561 default:
1562 return false;
1563 }
1564 addr_t sp_offset = imm32;
1565 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1566
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001567 EmulateInstruction::Context context;
1568 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1569 Register dwarf_reg;
1570 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1571 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001572
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001573 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001574 return false;
1575 }
1576 return true;
1577}
1578
Johnny Chenc9e747f2011-02-23 01:55:07 +00001579// This instruction subtracts an immediate value from the SP value, and writes
1580// the result to the destination register.
1581//
1582// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001583bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001584EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001585{
1586#if 0
1587 // ARM pseudo code...
1588 if (ConditionPassed())
1589 {
1590 EncodingSpecificOperations();
1591 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001592 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001593 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001594 else
1595 R[d] = result;
1596 if setflags then
1597 APSR.N = result<31>;
1598 APSR.Z = IsZeroBit(result);
1599 APSR.C = carry;
1600 APSR.V = overflow;
1601 }
1602#endif
1603
1604 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001605 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001606 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001607 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001608 if (!success)
1609 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001610
1611 uint32_t Rd;
1612 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001613 uint32_t imm32;
1614 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001615 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001616 Rd = 13;
1617 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001618 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001619 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001620 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001621 Rd = Bits32(opcode, 11, 8);
1622 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001623 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001624 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001625 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001626 if (Rd == 15 && !setflags)
1627 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001628 break;
1629 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001630 Rd = Bits32(opcode, 11, 8);
1631 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001632 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001633 if (Rd == 15)
1634 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001635 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001636 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001637 Rd = Bits32(opcode, 15, 12);
1638 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001639 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001640 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1641 // TODO: Emulate SUBS PC, LR and related instructions.
1642 if (Rd == 15 && setflags)
1643 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001644 break;
1645 default:
1646 return false;
1647 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001648 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1649
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001650 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001651 if (Rd == 13)
1652 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001653 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1654 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001655 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001656 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001657 }
1658 else
1659 {
1660 context.type = EmulateInstruction::eContextImmediate;
1661 context.SetNoArgs ();
1662 }
1663
1664 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001665 return false;
1666 }
1667 return true;
1668}
1669
Johnny Chen08c25e82011-01-31 18:02:28 +00001670// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001671bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001672EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001673{
1674#if 0
1675 // ARM pseudo code...
1676 if (ConditionPassed())
1677 {
1678 EncodingSpecificOperations();
1679 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1680 address = if index then offset_addr else R[n];
1681 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1682 if wback then R[n] = offset_addr;
1683 }
1684#endif
1685
1686 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001687
Greg Clayton7bc39082011-03-24 23:53:38 +00001688 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001689 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001690 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001691 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001692 if (!success)
1693 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001694 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001695 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001696 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1697
1698 bool index;
1699 bool add;
1700 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001701 switch (encoding) {
1702 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001703 Rt = Bits32(opcode, 15, 12);
1704 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001705 Rn = Bits32 (opcode, 19, 16);
1706
1707 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1708 return false;
1709
1710 index = BitIsSet (opcode, 24);
1711 add = BitIsSet (opcode, 23);
1712 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1713
1714 if (wback && ((Rn == 15) || (Rn == Rt)))
1715 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001716 break;
1717 default:
1718 return false;
1719 }
Caroline Tice3e407972011-03-18 19:41:00 +00001720 addr_t offset_addr;
1721 if (add)
1722 offset_addr = sp + imm12;
1723 else
1724 offset_addr = sp - imm12;
1725
1726 addr_t addr;
1727 if (index)
1728 addr = offset_addr;
1729 else
1730 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001731
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001732 EmulateInstruction::Context context;
1733 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001734 Register sp_reg;
1735 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1736 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001737 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001738 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001739 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001740 if (!success)
1741 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001742 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001743 return false;
1744 }
1745 else
1746 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001747 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001748 if (!success)
1749 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001750 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001751 return false;
1752 }
1753
Caroline Tice3e407972011-03-18 19:41:00 +00001754
1755 if (wback)
1756 {
1757 context.type = EmulateInstruction::eContextAdjustStackPointer;
1758 context.SetImmediateSigned (addr - sp);
1759 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1760 return false;
1761 }
Johnny Chence1ca772011-01-25 01:13:00 +00001762 }
1763 return true;
1764}
1765
Johnny Chen08c25e82011-01-31 18:02:28 +00001766// Vector Push stores multiple extension registers to the stack.
1767// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001769EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001770{
1771#if 0
1772 // ARM pseudo code...
1773 if (ConditionPassed())
1774 {
1775 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1776 address = SP - imm32;
1777 SP = SP - imm32;
1778 if single_regs then
1779 for r = 0 to regs-1
1780 MemA[address,4] = S[d+r]; address = address+4;
1781 else
1782 for r = 0 to regs-1
1783 // Store as two word-aligned words in the correct order for current endianness.
1784 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1785 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1786 address = address+8;
1787 }
1788#endif
1789
1790 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001791
Greg Clayton7bc39082011-03-24 23:53:38 +00001792 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001793 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001794 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001795 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001796 if (!success)
1797 return false;
1798 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001799 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001800 uint32_t imm32; // stack offset
1801 uint32_t regs; // number of registers
1802 switch (encoding) {
1803 case eEncodingT1:
1804 case eEncodingA1:
1805 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001806 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001807 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1808 // If UInt(imm8) is odd, see "FSTMX".
1809 regs = Bits32(opcode, 7, 0) / 2;
1810 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1811 if (regs == 0 || regs > 16 || (d + regs) > 32)
1812 return false;
1813 break;
1814 case eEncodingT2:
1815 case eEncodingA2:
1816 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001817 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001818 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1819 regs = Bits32(opcode, 7, 0);
1820 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1821 if (regs == 0 || regs > 16 || (d + regs) > 32)
1822 return false;
1823 break;
1824 default:
1825 return false;
1826 }
1827 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1828 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1829 addr_t sp_offset = imm32;
1830 addr_t addr = sp - sp_offset;
1831 uint32_t i;
1832
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001833 EmulateInstruction::Context context;
1834 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1835 Register dwarf_reg;
1836 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001837 for (i=d; i<regs; ++i)
1838 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001839 dwarf_reg.num = start_reg + i;
1840 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001841 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001842 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001843 if (!success)
1844 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001845 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001846 return false;
1847 addr += reg_byte_size;
1848 }
1849
1850 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001851 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001852
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001853 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001854 return false;
1855 }
1856 return true;
1857}
1858
Johnny Chen587a0a42011-02-01 18:35:28 +00001859// Vector Pop loads multiple extension registers from the stack.
1860// It also updates SP to point just above the loaded data.
1861bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001862EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001863{
1864#if 0
1865 // ARM pseudo code...
1866 if (ConditionPassed())
1867 {
1868 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1869 address = SP;
1870 SP = SP + imm32;
1871 if single_regs then
1872 for r = 0 to regs-1
1873 S[d+r] = MemA[address,4]; address = address+4;
1874 else
1875 for r = 0 to regs-1
1876 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1877 // Combine the word-aligned words in the correct order for current endianness.
1878 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1879 }
1880#endif
1881
1882 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001883
Greg Clayton7bc39082011-03-24 23:53:38 +00001884 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001885 {
1886 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001887 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001888 if (!success)
1889 return false;
1890 bool single_regs;
1891 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1892 uint32_t imm32; // stack offset
1893 uint32_t regs; // number of registers
1894 switch (encoding) {
1895 case eEncodingT1:
1896 case eEncodingA1:
1897 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001898 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001899 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1900 // If UInt(imm8) is odd, see "FLDMX".
1901 regs = Bits32(opcode, 7, 0) / 2;
1902 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1903 if (regs == 0 || regs > 16 || (d + regs) > 32)
1904 return false;
1905 break;
1906 case eEncodingT2:
1907 case eEncodingA2:
1908 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001909 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001910 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1911 regs = Bits32(opcode, 7, 0);
1912 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1913 if (regs == 0 || regs > 16 || (d + regs) > 32)
1914 return false;
1915 break;
1916 default:
1917 return false;
1918 }
1919 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1920 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1921 addr_t sp_offset = imm32;
1922 addr_t addr = sp;
1923 uint32_t i;
1924 uint64_t data; // uint64_t to accomodate 64-bit registers.
1925
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001926 EmulateInstruction::Context context;
1927 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1928 Register dwarf_reg;
1929 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001930 for (i=d; i<regs; ++i)
1931 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001932 dwarf_reg.num = start_reg + i;
1933 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001934 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001935 if (!success)
1936 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001937 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001938 return false;
1939 addr += reg_byte_size;
1940 }
1941
1942 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001943 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001944
1945 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1946 return false;
1947 }
1948 return true;
1949}
1950
Johnny Chenb77be412011-02-04 00:40:18 +00001951// SVC (previously SWI)
1952bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001953EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00001954{
1955#if 0
1956 // ARM pseudo code...
1957 if (ConditionPassed())
1958 {
1959 EncodingSpecificOperations();
1960 CallSupervisor();
1961 }
1962#endif
1963
1964 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00001965
Greg Clayton7bc39082011-03-24 23:53:38 +00001966 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00001967 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001968 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001969 addr_t lr; // next instruction address
1970 if (!success)
1971 return false;
1972 uint32_t imm32; // the immediate constant
1973 uint32_t mode; // ARM or Thumb mode
1974 switch (encoding) {
1975 case eEncodingT1:
1976 lr = (pc + 2) | 1u; // return address
1977 imm32 = Bits32(opcode, 7, 0);
1978 mode = eModeThumb;
1979 break;
1980 case eEncodingA1:
1981 lr = pc + 4; // return address
1982 imm32 = Bits32(opcode, 23, 0);
1983 mode = eModeARM;
1984 break;
1985 default:
1986 return false;
1987 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001988
1989 EmulateInstruction::Context context;
1990 context.type = EmulateInstruction::eContextSupervisorCall;
1991 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001992 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1993 return false;
1994 }
1995 return true;
1996}
1997
Johnny Chenc315f862011-02-05 00:46:10 +00001998// If Then makes up to four following instructions (the IT block) conditional.
1999bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002000EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002001{
2002#if 0
2003 // ARM pseudo code...
2004 EncodingSpecificOperations();
2005 ITSTATE.IT<7:0> = firstcond:mask;
2006#endif
2007
Johnny Chenc315f862011-02-05 00:46:10 +00002008 m_it_session.InitIT(Bits32(opcode, 7, 0));
2009 return true;
2010}
2011
Johnny Chen3b620b32011-02-07 20:11:47 +00002012// Branch causes a branch to a target address.
2013bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002014EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002015{
2016#if 0
2017 // ARM pseudo code...
2018 if (ConditionPassed())
2019 {
2020 EncodingSpecificOperations();
2021 BranchWritePC(PC + imm32);
2022 }
2023#endif
2024
2025 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002026
Greg Clayton7bc39082011-03-24 23:53:38 +00002027 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002028 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002029 EmulateInstruction::Context context;
2030 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002031 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002032 if (!success)
2033 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002034 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002035 int32_t imm32; // PC-relative offset
2036 switch (encoding) {
2037 case eEncodingT1:
2038 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2039 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002040 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002041 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002042 break;
2043 case eEncodingT2:
2044 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002045 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002046 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002047 break;
2048 case eEncodingT3:
2049 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2050 {
Johnny Chenbd599902011-02-10 21:39:01 +00002051 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002052 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002053 uint32_t J1 = Bit32(opcode, 13);
2054 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002055 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002056 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002057 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002058 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002059 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002060 break;
2061 }
2062 case eEncodingT4:
2063 {
Johnny Chenbd599902011-02-10 21:39:01 +00002064 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002065 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002066 uint32_t J1 = Bit32(opcode, 13);
2067 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002068 uint32_t imm11 = Bits32(opcode, 10, 0);
2069 uint32_t I1 = !(J1 ^ S);
2070 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002071 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002072 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002073 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002074 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002075 break;
2076 }
2077 case eEncodingA1:
2078 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002079 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002080 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002081 break;
2082 default:
2083 return false;
2084 }
2085 if (!BranchWritePC(context, target))
2086 return false;
2087 }
2088 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002089}
2090
Johnny Chen53ebab72011-02-08 23:21:57 +00002091// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2092// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2093// CBNZ, CBZ
2094bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002095EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002096{
2097#if 0
2098 // ARM pseudo code...
2099 EncodingSpecificOperations();
2100 if nonzero ^ IsZero(R[n]) then
2101 BranchWritePC(PC + imm32);
2102#endif
2103
2104 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002105
2106 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002107 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002108 if (!success)
2109 return false;
2110
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002111 EmulateInstruction::Context context;
2112 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002113 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002114 if (!success)
2115 return false;
2116
2117 addr_t target; // target address
2118 uint32_t imm32; // PC-relative offset to branch forward
2119 bool nonzero;
2120 switch (encoding) {
2121 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002122 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002123 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002124 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002125 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002126 break;
2127 default:
2128 return false;
2129 }
2130 if (nonzero ^ (reg_val == 0))
2131 if (!BranchWritePC(context, target))
2132 return false;
2133
2134 return true;
2135}
2136
Johnny Chen60299ec2011-02-17 19:34:27 +00002137// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2138// A base register provides a pointer to the table, and a second register supplies an index into the table.
2139// The branch length is twice the value of the byte returned from the table.
2140//
2141// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2142// A base register provides a pointer to the table, and a second register supplies an index into the table.
2143// The branch length is twice the value of the halfword returned from the table.
2144// TBB, TBH
2145bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002146EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002147{
2148#if 0
2149 // ARM pseudo code...
2150 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2151 if is_tbh then
2152 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2153 else
2154 halfwords = UInt(MemU[R[n]+R[m], 1]);
2155 BranchWritePC(PC + 2*halfwords);
2156#endif
2157
2158 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002159
2160 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2161 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2162 bool is_tbh; // true if table branch halfword
2163 switch (encoding) {
2164 case eEncodingT1:
2165 Rn = Bits32(opcode, 19, 16);
2166 Rm = Bits32(opcode, 3, 0);
2167 is_tbh = BitIsSet(opcode, 4);
2168 if (Rn == 13 || BadReg(Rm))
2169 return false;
2170 if (InITBlock() && !LastInITBlock())
2171 return false;
2172 break;
2173 default:
2174 return false;
2175 }
2176
2177 // Read the address of the table from the operand register Rn.
2178 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002179 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002180 if (!success)
2181 return false;
2182
2183 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002184 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002185 if (!success)
2186 return false;
2187
2188 // the offsetted table address
2189 addr_t addr = base + (is_tbh ? index*2 : index);
2190
2191 // PC-relative offset to branch forward
2192 EmulateInstruction::Context context;
2193 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002194 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002195 if (!success)
2196 return false;
2197
Johnny Chene39f22d2011-02-19 01:36:13 +00002198 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002199 if (!success)
2200 return false;
2201
2202 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002203 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002204 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2205 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2206
2207 if (!BranchWritePC(context, target))
2208 return false;
2209
2210 return true;
2211}
2212
Caroline Ticedcc11b32011-03-02 23:57:02 +00002213// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2214// It can optionally update the condition flags based on the result.
2215bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002216EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002217{
2218#if 0
2219 if ConditionPassed() then
2220 EncodingSpecificOperations();
2221 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2222 R[d] = result;
2223 if setflags then
2224 APSR.N = result<31>;
2225 APSR.Z = IsZeroBit(result);
2226 APSR.C = carry;
2227 APSR.V = overflow;
2228#endif
2229
2230 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002231
Greg Clayton7bc39082011-03-24 23:53:38 +00002232 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002233 {
2234 uint32_t d;
2235 uint32_t n;
2236 bool setflags;
2237 uint32_t imm32;
2238 uint32_t carry_out;
2239
2240 //EncodingSpecificOperations();
2241 switch (encoding)
2242 {
2243 case eEncodingT1:
2244 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2245 d = Bits32 (opcode, 2, 0);
2246 n = Bits32 (opcode, 5, 3);
2247 setflags = !InITBlock();
2248 imm32 = Bits32 (opcode, 8,6);
2249
2250 break;
2251
2252 case eEncodingT2:
2253 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2254 d = Bits32 (opcode, 10, 8);
2255 n = Bits32 (opcode, 10, 8);
2256 setflags = !InITBlock();
2257 imm32 = Bits32 (opcode, 7, 0);
2258
2259 break;
2260
2261 case eEncodingT3:
2262 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2263 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2264 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2265 d = Bits32 (opcode, 11, 8);
2266 n = Bits32 (opcode, 19, 16);
2267 setflags = BitIsSet (opcode, 20);
2268 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2269
2270 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2271 if (BadReg (d) || (n == 15))
2272 return false;
2273
2274 break;
2275
2276 case eEncodingT4:
2277 {
2278 // if Rn == ’1111’ then SEE ADR;
2279 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2280 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2281 d = Bits32 (opcode, 11, 8);
2282 n = Bits32 (opcode, 19, 16);
2283 setflags = false;
2284 uint32_t i = Bit32 (opcode, 26);
2285 uint32_t imm3 = Bits32 (opcode, 14, 12);
2286 uint32_t imm8 = Bits32 (opcode, 7, 0);
2287 imm32 = (i << 11) | (imm3 << 8) | imm8;
2288
2289 // if BadReg(d) then UNPREDICTABLE;
2290 if (BadReg (d))
2291 return false;
2292
2293 break;
2294 }
2295 default:
2296 return false;
2297 }
2298
2299 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2300 if (!success)
2301 return false;
2302
2303 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2304 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2305
2306 Register reg_n;
2307 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2308
2309 EmulateInstruction::Context context;
2310 context.type = eContextAddition;
2311 context.SetRegisterPlusOffset (reg_n, imm32);
2312
2313 //R[d] = result;
2314 //if setflags then
2315 //APSR.N = result<31>;
2316 //APSR.Z = IsZeroBit(result);
2317 //APSR.C = carry;
2318 //APSR.V = overflow;
2319 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2320 return false;
2321
2322 }
2323 return true;
2324}
2325
Johnny Chen8fa20592011-02-18 01:22:22 +00002326// This instruction adds an immediate value to a register value, and writes the result to the destination
2327// register. It can optionally update the condition flags based on the result.
2328bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002329EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002330{
2331#if 0
2332 // ARM pseudo code...
2333 if ConditionPassed() then
2334 EncodingSpecificOperations();
2335 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2336 if d == 15 then
2337 ALUWritePC(result); // setflags is always FALSE here
2338 else
2339 R[d] = result;
2340 if setflags then
2341 APSR.N = result<31>;
2342 APSR.Z = IsZeroBit(result);
2343 APSR.C = carry;
2344 APSR.V = overflow;
2345#endif
2346
2347 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002348
Greg Clayton7bc39082011-03-24 23:53:38 +00002349 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002350 {
2351 uint32_t Rd, Rn;
2352 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2353 bool setflags;
2354 switch (encoding)
2355 {
2356 case eEncodingA1:
2357 Rd = Bits32(opcode, 15, 12);
2358 Rn = Bits32(opcode, 19, 16);
2359 setflags = BitIsSet(opcode, 20);
2360 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2361 break;
2362 default:
2363 return false;
2364 }
2365
Johnny Chen8fa20592011-02-18 01:22:22 +00002366 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002367 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002368 if (!success)
2369 return false;
2370
2371 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2372
2373 EmulateInstruction::Context context;
2374 context.type = EmulateInstruction::eContextImmediate;
2375 context.SetNoArgs ();
2376
2377 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2378 return false;
2379 }
2380 return true;
2381}
2382
Johnny Chend761dcf2011-02-17 22:03:29 +00002383// This instruction adds a register value and an optionally-shifted register value, and writes the result
2384// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002385bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002386EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002387{
2388#if 0
2389 // ARM pseudo code...
2390 if ConditionPassed() then
2391 EncodingSpecificOperations();
2392 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2393 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2394 if d == 15 then
2395 ALUWritePC(result); // setflags is always FALSE here
2396 else
2397 R[d] = result;
2398 if setflags then
2399 APSR.N = result<31>;
2400 APSR.Z = IsZeroBit(result);
2401 APSR.C = carry;
2402 APSR.V = overflow;
2403#endif
2404
2405 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002406
Greg Clayton7bc39082011-03-24 23:53:38 +00002407 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002408 {
2409 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002410 ARM_ShifterType shift_t;
2411 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002412 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002413 switch (encoding)
2414 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002415 case eEncodingT1:
2416 Rd = Bits32(opcode, 2, 0);
2417 Rn = Bits32(opcode, 5, 3);
2418 Rm = Bits32(opcode, 8, 6);
2419 setflags = !InITBlock();
2420 shift_t = SRType_LSL;
2421 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002422 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002423 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002424 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002425 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002426 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002427 shift_t = SRType_LSL;
2428 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002429 if (Rn == 15 && Rm == 15)
2430 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002431 if (Rd == 15 && InITBlock() && !LastInITBlock())
2432 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002433 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002434 case eEncodingA1:
2435 Rd = Bits32(opcode, 15, 12);
2436 Rn = Bits32(opcode, 19, 16);
2437 Rm = Bits32(opcode, 3, 0);
2438 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002439 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002440 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002441 default:
2442 return false;
2443 }
2444
Johnny Chen26863dc2011-02-09 23:43:29 +00002445 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002446 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002447 if (!success)
2448 return false;
2449
2450 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002451 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002452 if (!success)
2453 return false;
2454
Johnny Chene97c0d52011-02-18 19:32:20 +00002455 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002456 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002457
2458 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002459 context.type = EmulateInstruction::eContextAddition;
2460 Register op1_reg;
2461 Register op2_reg;
2462 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2463 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2464 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002465
Johnny Chen10530c22011-02-17 22:37:12 +00002466 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002467 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002468 }
2469 return true;
2470}
2471
Johnny Chen34075cb2011-02-22 01:56:31 +00002472// Compare Negative (immediate) adds a register value and an immediate value.
2473// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002474bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002475EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002476{
2477#if 0
2478 // ARM pseudo code...
2479 if ConditionPassed() then
2480 EncodingSpecificOperations();
2481 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2482 APSR.N = result<31>;
2483 APSR.Z = IsZeroBit(result);
2484 APSR.C = carry;
2485 APSR.V = overflow;
2486#endif
2487
2488 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002489
2490 uint32_t Rn; // the first operand
2491 uint32_t imm32; // the immediate value to be compared with
2492 switch (encoding) {
2493 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002494 Rn = Bits32(opcode, 19, 16);
2495 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2496 if (Rn == 15)
2497 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002498 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002499 case eEncodingA1:
2500 Rn = Bits32(opcode, 19, 16);
2501 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2502 break;
2503 default:
2504 return false;
2505 }
2506 // Read the register value from the operand register Rn.
2507 uint32_t reg_val = ReadCoreReg(Rn, &success);
2508 if (!success)
2509 return false;
2510
Johnny Chen078fbc62011-02-22 19:48:22 +00002511 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002512
2513 EmulateInstruction::Context context;
2514 context.type = EmulateInstruction::eContextImmediate;
2515 context.SetNoArgs ();
2516 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2517 return false;
2518
2519 return true;
2520}
2521
2522// Compare Negative (register) adds a register value and an optionally-shifted register value.
2523// It updates the condition flags based on the result, and discards the result.
2524bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002525EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002526{
2527#if 0
2528 // ARM pseudo code...
2529 if ConditionPassed() then
2530 EncodingSpecificOperations();
2531 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2532 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2533 APSR.N = result<31>;
2534 APSR.Z = IsZeroBit(result);
2535 APSR.C = carry;
2536 APSR.V = overflow;
2537#endif
2538
2539 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002540
2541 uint32_t Rn; // the first operand
2542 uint32_t Rm; // the second operand
2543 ARM_ShifterType shift_t;
2544 uint32_t shift_n; // the shift applied to the value read from Rm
2545 switch (encoding) {
2546 case eEncodingT1:
2547 Rn = Bits32(opcode, 2, 0);
2548 Rm = Bits32(opcode, 5, 3);
2549 shift_t = SRType_LSL;
2550 shift_n = 0;
2551 break;
2552 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002553 Rn = Bits32(opcode, 19, 16);
2554 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002555 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002556 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2557 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002558 return false;
2559 break;
2560 case eEncodingA1:
2561 Rn = Bits32(opcode, 19, 16);
2562 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002563 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002564 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002565 default:
2566 return false;
2567 }
2568 // Read the register value from register Rn.
2569 uint32_t val1 = ReadCoreReg(Rn, &success);
2570 if (!success)
2571 return false;
2572
2573 // Read the register value from register Rm.
2574 uint32_t val2 = ReadCoreReg(Rm, &success);
2575 if (!success)
2576 return false;
2577
2578 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002579 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002580
2581 EmulateInstruction::Context context;
2582 context.type = EmulateInstruction::eContextImmediate;
2583 context.SetNoArgs();
2584 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2585 return false;
2586
2587 return true;
2588}
2589
2590// Compare (immediate) subtracts an immediate value from a register value.
2591// It updates the condition flags based on the result, and discards the result.
2592bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002593EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002594{
2595#if 0
2596 // ARM pseudo code...
2597 if ConditionPassed() then
2598 EncodingSpecificOperations();
2599 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2600 APSR.N = result<31>;
2601 APSR.Z = IsZeroBit(result);
2602 APSR.C = carry;
2603 APSR.V = overflow;
2604#endif
2605
2606 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002607
2608 uint32_t Rn; // the first operand
2609 uint32_t imm32; // the immediate value to be compared with
2610 switch (encoding) {
2611 case eEncodingT1:
2612 Rn = Bits32(opcode, 10, 8);
2613 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002614 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002615 case eEncodingT2:
2616 Rn = Bits32(opcode, 19, 16);
2617 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2618 if (Rn == 15)
2619 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002620 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002621 case eEncodingA1:
2622 Rn = Bits32(opcode, 19, 16);
2623 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002624 break;
2625 default:
2626 return false;
2627 }
2628 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002629 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002630 if (!success)
2631 return false;
2632
Johnny Chen10530c22011-02-17 22:37:12 +00002633 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2634
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002635 EmulateInstruction::Context context;
2636 context.type = EmulateInstruction::eContextImmediate;
2637 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002638 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2639 return false;
2640
Johnny Chend4dc4442011-02-11 02:02:56 +00002641 return true;
2642}
2643
Johnny Chen34075cb2011-02-22 01:56:31 +00002644// Compare (register) subtracts an optionally-shifted register value from a register value.
2645// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002646bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002647EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002648{
2649#if 0
2650 // ARM pseudo code...
2651 if ConditionPassed() then
2652 EncodingSpecificOperations();
2653 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2654 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2655 APSR.N = result<31>;
2656 APSR.Z = IsZeroBit(result);
2657 APSR.C = carry;
2658 APSR.V = overflow;
2659#endif
2660
2661 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002662
2663 uint32_t Rn; // the first operand
2664 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002665 ARM_ShifterType shift_t;
2666 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002667 switch (encoding) {
2668 case eEncodingT1:
2669 Rn = Bits32(opcode, 2, 0);
2670 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002671 shift_t = SRType_LSL;
2672 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002673 break;
2674 case eEncodingT2:
2675 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2676 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002677 shift_t = SRType_LSL;
2678 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002679 if (Rn < 8 && Rm < 8)
2680 return false;
2681 if (Rn == 15 || Rm == 15)
2682 return false;
2683 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002684 case eEncodingA1:
2685 Rn = Bits32(opcode, 19, 16);
2686 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002687 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002688 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002689 default:
2690 return false;
2691 }
2692 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002693 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002694 if (!success)
2695 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002696
Johnny Chene4a4d302011-02-11 21:53:58 +00002697 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002698 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002699 if (!success)
2700 return false;
2701
Johnny Chen34075cb2011-02-22 01:56:31 +00002702 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2703 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002704
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002705 EmulateInstruction::Context context;
2706 context.type = EmulateInstruction::eContextImmediate;
2707 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002708 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2709 return false;
2710
Johnny Chene4a4d302011-02-11 21:53:58 +00002711 return true;
2712}
2713
Johnny Chen82f16aa2011-02-15 20:10:55 +00002714// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2715// shifting in copies of its sign bit, and writes the result to the destination register. It can
2716// optionally update the condition flags based on the result.
2717bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002718EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002719{
2720#if 0
2721 // ARM pseudo code...
2722 if ConditionPassed() then
2723 EncodingSpecificOperations();
2724 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2725 if d == 15 then // Can only occur for ARM encoding
2726 ALUWritePC(result); // setflags is always FALSE here
2727 else
2728 R[d] = result;
2729 if setflags then
2730 APSR.N = result<31>;
2731 APSR.Z = IsZeroBit(result);
2732 APSR.C = carry;
2733 // APSR.V unchanged
2734#endif
2735
Greg Clayton7bc39082011-03-24 23:53:38 +00002736 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002737}
2738
2739// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2740// shifting in copies of its sign bit, and writes the result to the destination register.
2741// The variable number of bits is read from the bottom byte of a register. It can optionally update
2742// the condition flags based on the result.
2743bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002744EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002745{
2746#if 0
2747 // ARM pseudo code...
2748 if ConditionPassed() then
2749 EncodingSpecificOperations();
2750 shift_n = UInt(R[m]<7:0>);
2751 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2752 R[d] = result;
2753 if setflags then
2754 APSR.N = result<31>;
2755 APSR.Z = IsZeroBit(result);
2756 APSR.C = carry;
2757 // APSR.V unchanged
2758#endif
2759
Greg Clayton7bc39082011-03-24 23:53:38 +00002760 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002761}
2762
2763// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2764// shifting in zeros, and writes the result to the destination register. It can optionally
2765// update the condition flags based on the result.
2766bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002767EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002768{
2769#if 0
2770 // ARM pseudo code...
2771 if ConditionPassed() then
2772 EncodingSpecificOperations();
2773 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2774 if d == 15 then // Can only occur for ARM encoding
2775 ALUWritePC(result); // setflags is always FALSE here
2776 else
2777 R[d] = result;
2778 if setflags then
2779 APSR.N = result<31>;
2780 APSR.Z = IsZeroBit(result);
2781 APSR.C = carry;
2782 // APSR.V unchanged
2783#endif
2784
Greg Clayton7bc39082011-03-24 23:53:38 +00002785 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002786}
2787
2788// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2789// shifting in zeros, and writes the result to the destination register. The variable number
2790// of bits is read from the bottom byte of a register. It can optionally update the condition
2791// flags based on the result.
2792bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002793EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002794{
2795#if 0
2796 // ARM pseudo code...
2797 if ConditionPassed() then
2798 EncodingSpecificOperations();
2799 shift_n = UInt(R[m]<7:0>);
2800 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2801 R[d] = result;
2802 if setflags then
2803 APSR.N = result<31>;
2804 APSR.Z = IsZeroBit(result);
2805 APSR.C = carry;
2806 // APSR.V unchanged
2807#endif
2808
Greg Clayton7bc39082011-03-24 23:53:38 +00002809 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002810}
2811
2812// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2813// shifting in zeros, and writes the result to the destination register. It can optionally
2814// update the condition flags based on the result.
2815bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002816EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002817{
2818#if 0
2819 // ARM pseudo code...
2820 if ConditionPassed() then
2821 EncodingSpecificOperations();
2822 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2823 if d == 15 then // Can only occur for ARM encoding
2824 ALUWritePC(result); // setflags is always FALSE here
2825 else
2826 R[d] = result;
2827 if setflags then
2828 APSR.N = result<31>;
2829 APSR.Z = IsZeroBit(result);
2830 APSR.C = carry;
2831 // APSR.V unchanged
2832#endif
2833
Greg Clayton7bc39082011-03-24 23:53:38 +00002834 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002835}
2836
2837// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2838// shifting in zeros, and writes the result to the destination register. The variable number
2839// of bits is read from the bottom byte of a register. It can optionally update the condition
2840// flags based on the result.
2841bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002842EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002843{
2844#if 0
2845 // ARM pseudo code...
2846 if ConditionPassed() then
2847 EncodingSpecificOperations();
2848 shift_n = UInt(R[m]<7:0>);
2849 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2850 R[d] = result;
2851 if setflags then
2852 APSR.N = result<31>;
2853 APSR.Z = IsZeroBit(result);
2854 APSR.C = carry;
2855 // APSR.V unchanged
2856#endif
2857
Greg Clayton7bc39082011-03-24 23:53:38 +00002858 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002859}
2860
Johnny Cheneeab4852011-02-16 22:14:44 +00002861// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2862// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2863// It can optionally update the condition flags based on the result.
2864bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002865EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002866{
2867#if 0
2868 // ARM pseudo code...
2869 if ConditionPassed() then
2870 EncodingSpecificOperations();
2871 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2872 if d == 15 then // Can only occur for ARM encoding
2873 ALUWritePC(result); // setflags is always FALSE here
2874 else
2875 R[d] = result;
2876 if setflags then
2877 APSR.N = result<31>;
2878 APSR.Z = IsZeroBit(result);
2879 APSR.C = carry;
2880 // APSR.V unchanged
2881#endif
2882
Greg Clayton7bc39082011-03-24 23:53:38 +00002883 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002884}
2885
2886// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2887// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2888// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2889// flags based on the result.
2890bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002891EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002892{
2893#if 0
2894 // ARM pseudo code...
2895 if ConditionPassed() then
2896 EncodingSpecificOperations();
2897 shift_n = UInt(R[m]<7:0>);
2898 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2899 R[d] = result;
2900 if setflags then
2901 APSR.N = result<31>;
2902 APSR.Z = IsZeroBit(result);
2903 APSR.C = carry;
2904 // APSR.V unchanged
2905#endif
2906
Greg Clayton7bc39082011-03-24 23:53:38 +00002907 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002908}
2909
2910// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2911// with the carry flag shifted into bit [31].
2912//
2913// RRX can optionally update the condition flags based on the result.
2914// In that case, bit [0] is shifted into the carry flag.
2915bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002916EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002917{
2918#if 0
2919 // ARM pseudo code...
2920 if ConditionPassed() then
2921 EncodingSpecificOperations();
2922 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2923 if d == 15 then // Can only occur for ARM encoding
2924 ALUWritePC(result); // setflags is always FALSE here
2925 else
2926 R[d] = result;
2927 if setflags then
2928 APSR.N = result<31>;
2929 APSR.Z = IsZeroBit(result);
2930 APSR.C = carry;
2931 // APSR.V unchanged
2932#endif
2933
Greg Clayton7bc39082011-03-24 23:53:38 +00002934 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00002935}
2936
Johnny Chen41a0a152011-02-16 01:27:54 +00002937bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002938EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00002939{
2940 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2941
Johnny Chen82f16aa2011-02-15 20:10:55 +00002942 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002943
Greg Clayton7bc39082011-03-24 23:53:38 +00002944 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002945 {
Johnny Chene7f89532011-02-15 23:22:46 +00002946 uint32_t Rd; // the destination register
2947 uint32_t Rm; // the first operand register
2948 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002949 uint32_t carry; // the carry bit after the shift operation
2950 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002951
2952 // Special case handling!
2953 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00002954 ARMEncoding use_encoding = encoding;
2955 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00002956 {
2957 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2958 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00002959 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00002960 }
2961
Greg Clayton7bc39082011-03-24 23:53:38 +00002962 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00002963 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002964 // Due to the above special case handling!
2965 assert(shift_type != SRType_ROR);
2966
Johnny Chen82f16aa2011-02-15 20:10:55 +00002967 Rd = Bits32(opcode, 2, 0);
2968 Rm = Bits32(opcode, 5, 3);
2969 setflags = !InITBlock();
2970 imm5 = Bits32(opcode, 10, 6);
2971 break;
2972 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002973 // A8.6.141 RRX
2974 assert(shift_type != SRType_RRX);
2975
Johnny Chen82f16aa2011-02-15 20:10:55 +00002976 Rd = Bits32(opcode, 11, 8);
2977 Rm = Bits32(opcode, 3, 0);
2978 setflags = BitIsSet(opcode, 20);
2979 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2980 if (BadReg(Rd) || BadReg(Rm))
2981 return false;
2982 break;
2983 case eEncodingA1:
2984 Rd = Bits32(opcode, 15, 12);
2985 Rm = Bits32(opcode, 3, 0);
2986 setflags = BitIsSet(opcode, 20);
2987 imm5 = Bits32(opcode, 11, 7);
2988 break;
2989 default:
2990 return false;
2991 }
2992
Johnny Cheneeab4852011-02-16 22:14:44 +00002993 // A8.6.139 ROR (immediate)
2994 if (shift_type == SRType_ROR && imm5 == 0)
2995 shift_type = SRType_RRX;
2996
Johnny Chen82f16aa2011-02-15 20:10:55 +00002997 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002998 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002999 if (!success)
3000 return false;
3001
Johnny Cheneeab4852011-02-16 22:14:44 +00003002 // Decode the shift amount if not RRX.
3003 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003004
Johnny Chene97c0d52011-02-18 19:32:20 +00003005 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003006
3007 // The context specifies that an immediate is to be moved into Rd.
3008 EmulateInstruction::Context context;
3009 context.type = EmulateInstruction::eContextImmediate;
3010 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003011
Johnny Chen10530c22011-02-17 22:37:12 +00003012 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003013 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003014 }
3015 return true;
3016}
3017
Johnny Chene7f89532011-02-15 23:22:46 +00003018bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003019EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003020{
Johnny Chen41a0a152011-02-16 01:27:54 +00003021 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003022
3023 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003024
Greg Clayton7bc39082011-03-24 23:53:38 +00003025 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003026 {
3027 uint32_t Rd; // the destination register
3028 uint32_t Rn; // the first operand register
3029 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3030 uint32_t carry; // the carry bit after the shift operation
3031 bool setflags;
3032 switch (encoding) {
3033 case eEncodingT1:
3034 Rd = Bits32(opcode, 2, 0);
3035 Rn = Rd;
3036 Rm = Bits32(opcode, 5, 3);
3037 setflags = !InITBlock();
3038 break;
3039 case eEncodingT2:
3040 Rd = Bits32(opcode, 11, 8);
3041 Rn = Bits32(opcode, 19, 16);
3042 Rm = Bits32(opcode, 3, 0);
3043 setflags = BitIsSet(opcode, 20);
3044 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3045 return false;
3046 break;
3047 case eEncodingA1:
3048 Rd = Bits32(opcode, 15, 12);
3049 Rn = Bits32(opcode, 3, 0);
3050 Rm = Bits32(opcode, 11, 8);
3051 setflags = BitIsSet(opcode, 20);
3052 if (Rd == 15 || Rn == 15 || Rm == 15)
3053 return false;
3054 break;
3055 default:
3056 return false;
3057 }
3058
3059 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003060 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003061 if (!success)
3062 return false;
3063 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003064 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003065 if (!success)
3066 return false;
3067
3068 // Get the shift amount.
3069 uint32_t amt = Bits32(val, 7, 0);
3070
Johnny Chene97c0d52011-02-18 19:32:20 +00003071 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003072
3073 // The context specifies that an immediate is to be moved into Rd.
3074 EmulateInstruction::Context context;
3075 context.type = EmulateInstruction::eContextImmediate;
3076 context.SetNoArgs ();
3077
Johnny Chen10530c22011-02-17 22:37:12 +00003078 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003079 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003080 }
3081 return true;
3082}
3083
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003084// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003085// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003086// can be written back to the base register.
3087bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003088EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003089{
3090#if 0
3091 // ARM pseudo code...
3092 if ConditionPassed()
3093 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3094 address = R[n];
3095
3096 for i = 0 to 14
3097 if registers<i> == '1' then
3098 R[i] = MemA[address, 4]; address = address + 4;
3099 if registers<15> == '1' then
3100 LoadWritePC (MemA[address, 4]);
3101
3102 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3103 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3104
3105#endif
3106
3107 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003108
Greg Clayton7bc39082011-03-24 23:53:38 +00003109 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003110 {
3111 uint32_t n;
3112 uint32_t registers = 0;
3113 bool wback;
3114 const uint32_t addr_byte_size = GetAddressByteSize();
3115 switch (encoding)
3116 {
3117 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003118 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003119 n = Bits32 (opcode, 10, 8);
3120 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003121 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003122 wback = BitIsClear (registers, n);
3123 // if BitCount(registers) < 1 then UNPREDICTABLE;
3124 if (BitCount(registers) < 1)
3125 return false;
3126 break;
3127 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003128 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3129 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003130 n = Bits32 (opcode, 19, 16);
3131 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003132 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003133 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003134
3135 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003136 if ((n == 15)
3137 || (BitCount (registers) < 2)
3138 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3139 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003140
3141 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003142 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003143 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003144
3145 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003146 if (wback
3147 && BitIsSet (registers, n))
3148 return false;
3149 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003150
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003151 case eEncodingA1:
3152 n = Bits32 (opcode, 19, 16);
3153 registers = Bits32 (opcode, 15, 0);
3154 wback = BitIsSet (opcode, 21);
3155 if ((n == 15)
3156 || (BitCount (registers) < 1))
3157 return false;
3158 break;
3159 default:
3160 return false;
3161 }
3162
3163 int32_t offset = 0;
3164 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3165 if (!success)
3166 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003167
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003168 EmulateInstruction::Context context;
3169 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3170 Register dwarf_reg;
3171 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3172 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003173
3174 for (int i = 0; i < 14; ++i)
3175 {
3176 if (BitIsSet (registers, i))
3177 {
Caroline Tice85aab332011-02-08 23:56:10 +00003178 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003179 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003180 if (wback && (n == 13)) // Pop Instruction
3181 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3182
3183 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003184 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003185 if (!success)
3186 return false;
3187
3188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3189 return false;
3190
3191 offset += addr_byte_size;
3192 }
3193 }
3194
3195 if (BitIsSet (registers, 15))
3196 {
3197 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003198 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003199 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003200 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003201 if (!success)
3202 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003203 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003204 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003205 return false;
3206 }
3207
3208 if (wback && BitIsClear (registers, n))
3209 {
Caroline Ticefa172202011-02-11 22:49:54 +00003210 // R[n] = R[n] + 4 * BitCount (registers)
3211 int32_t offset = addr_byte_size * BitCount (registers);
3212 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003213 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003214
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003215 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3216 return false;
3217 }
3218 if (wback && BitIsSet (registers, n))
3219 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003220 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003221 }
3222 return true;
3223}
Caroline Tice713c2662011-02-11 17:59:55 +00003224
3225// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3226// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3227// can optionally be written back tot he base registers.
3228bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003229EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003230{
3231#if 0
3232 // ARM pseudo code...
3233 if ConditionPassed() then
3234 EncodingSpecificOperations();
3235 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003236
Caroline Tice713c2662011-02-11 17:59:55 +00003237 for i = 0 to 14
3238 if registers<i> == ’1’ then
3239 R[i] = MemA[address,4]; address = address + 4;
3240
3241 if registers<15> == ’1’ then
3242 LoadWritePC(MemA[address,4]);
3243
3244 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3245 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3246#endif
3247
3248 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003249
Greg Clayton7bc39082011-03-24 23:53:38 +00003250 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003251 {
3252 uint32_t n;
3253 uint32_t registers = 0;
3254 bool wback;
3255 const uint32_t addr_byte_size = GetAddressByteSize();
3256
3257 // EncodingSpecificOperations();
3258 switch (encoding)
3259 {
3260 case eEncodingA1:
3261 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3262 n = Bits32 (opcode, 19, 16);
3263 registers = Bits32 (opcode, 15, 0);
3264 wback = BitIsSet (opcode, 21);
3265
3266 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3267 if ((n == 15) || (BitCount (registers) < 1))
3268 return false;
3269
3270 break;
3271
3272 default:
3273 return false;
3274 }
3275 // address = R[n] - 4*BitCount(registers) + 4;
3276
3277 int32_t offset = 0;
3278 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3279
3280 if (!success)
3281 return false;
3282
3283 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3284
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003285 EmulateInstruction::Context context;
3286 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3287 Register dwarf_reg;
3288 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3289 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003290
3291 // for i = 0 to 14
3292 for (int i = 0; i < 14; ++i)
3293 {
3294 // if registers<i> == ’1’ then
3295 if (BitIsSet (registers, i))
3296 {
3297 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003298 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003299 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003300 if (!success)
3301 return false;
3302 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3303 return false;
3304 offset += addr_byte_size;
3305 }
3306 }
3307
3308 // if registers<15> == ’1’ then
3309 // LoadWritePC(MemA[address,4]);
3310 if (BitIsSet (registers, 15))
3311 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003312 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003313 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003314 if (!success)
3315 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003316 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003317 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003318 return false;
3319 }
3320
3321 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3322 if (wback && BitIsClear (registers, n))
3323 {
Caroline Tice713c2662011-02-11 17:59:55 +00003324 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3325 if (!success)
3326 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003327
3328 offset = (addr_byte_size * BitCount (registers)) * -1;
3329 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003330 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003331 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003332 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3333 return false;
3334 }
3335
3336 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3337 if (wback && BitIsSet (registers, n))
3338 return WriteBits32Unknown (n);
3339 }
3340 return true;
3341}
3342
3343// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3344// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3345// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003346bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003347EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003348{
3349#if 0
3350 // ARM pseudo code...
3351 if ConditionPassed() then
3352 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3353 address = R[n] - 4*BitCount(registers);
3354
3355 for i = 0 to 14
3356 if registers<i> == ’1’ then
3357 R[i] = MemA[address,4]; address = address + 4;
3358 if registers<15> == ’1’ then
3359 LoadWritePC(MemA[address,4]);
3360
3361 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3362 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3363#endif
3364
3365 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003366
Greg Clayton7bc39082011-03-24 23:53:38 +00003367 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003368 {
3369 uint32_t n;
3370 uint32_t registers = 0;
3371 bool wback;
3372 const uint32_t addr_byte_size = GetAddressByteSize();
3373 switch (encoding)
3374 {
3375 case eEncodingT1:
3376 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3377 n = Bits32 (opcode, 19, 16);
3378 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003379 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003380 wback = BitIsSet (opcode, 21);
3381
3382 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3383 if ((n == 15)
3384 || (BitCount (registers) < 2)
3385 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3386 return false;
3387
3388 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003389 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003390 return false;
3391
3392 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3393 if (wback && BitIsSet (registers, n))
3394 return false;
3395
3396 break;
3397
3398 case eEncodingA1:
3399 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3400 n = Bits32 (opcode, 19, 16);
3401 registers = Bits32 (opcode, 15, 0);
3402 wback = BitIsSet (opcode, 21);
3403
3404 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3405 if ((n == 15) || (BitCount (registers) < 1))
3406 return false;
3407
3408 break;
3409
3410 default:
3411 return false;
3412 }
3413
Caroline Tice713c2662011-02-11 17:59:55 +00003414 // address = R[n] - 4*BitCount(registers);
3415
Caroline Tice0b29e242011-02-08 23:16:02 +00003416 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003417 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3418
3419 if (!success)
3420 return false;
3421
3422 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003423 EmulateInstruction::Context context;
3424 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3425 Register dwarf_reg;
3426 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3427 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003428
3429 for (int i = 0; i < 14; ++i)
3430 {
3431 if (BitIsSet (registers, i))
3432 {
3433 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003434 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003435 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003436 if (!success)
3437 return false;
3438
3439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3440 return false;
3441
3442 offset += addr_byte_size;
3443 }
3444 }
3445
3446 // if registers<15> == ’1’ then
3447 // LoadWritePC(MemA[address,4]);
3448 if (BitIsSet (registers, 15))
3449 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003450 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003451 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003452 if (!success)
3453 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003454 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003455 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003456 return false;
3457 }
3458
3459 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3460 if (wback && BitIsClear (registers, n))
3461 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003462 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3463 if (!success)
3464 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003465
3466 offset = (addr_byte_size * BitCount (registers)) * -1;
3467 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003468 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003469 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003470 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3471 return false;
3472 }
3473
3474 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3475 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003476 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003477 }
3478 return true;
3479}
Caroline Tice85aab332011-02-08 23:56:10 +00003480
Caroline Tice713c2662011-02-11 17:59:55 +00003481// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3482// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3483// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003484bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003485EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003486{
3487#if 0
3488 if ConditionPassed() then
3489 EncodingSpecificOperations();
3490 address = R[n] + 4;
3491
3492 for i = 0 to 14
3493 if registers<i> == ’1’ then
3494 R[i] = MemA[address,4]; address = address + 4;
3495 if registers<15> == ’1’ then
3496 LoadWritePC(MemA[address,4]);
3497
3498 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3499 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3500#endif
3501
3502 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003503
Greg Clayton7bc39082011-03-24 23:53:38 +00003504 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003505 {
3506 uint32_t n;
3507 uint32_t registers = 0;
3508 bool wback;
3509 const uint32_t addr_byte_size = GetAddressByteSize();
3510 switch (encoding)
3511 {
3512 case eEncodingA1:
3513 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3514 n = Bits32 (opcode, 19, 16);
3515 registers = Bits32 (opcode, 15, 0);
3516 wback = BitIsSet (opcode, 21);
3517
3518 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3519 if ((n == 15) || (BitCount (registers) < 1))
3520 return false;
3521
3522 break;
3523 default:
3524 return false;
3525 }
3526 // address = R[n] + 4;
3527
3528 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003529 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3530
3531 if (!success)
3532 return false;
3533
3534 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003535
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003536 EmulateInstruction::Context context;
3537 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3538 Register dwarf_reg;
3539 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3540 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003541
3542 for (int i = 0; i < 14; ++i)
3543 {
3544 if (BitIsSet (registers, i))
3545 {
3546 // R[i] = MemA[address,4]; address = address + 4;
3547
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003548 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003549 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003550 if (!success)
3551 return false;
3552
3553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3554 return false;
3555
3556 offset += addr_byte_size;
3557 }
3558 }
3559
3560 // if registers<15> == ’1’ then
3561 // LoadWritePC(MemA[address,4]);
3562 if (BitIsSet (registers, 15))
3563 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003564 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003565 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003566 if (!success)
3567 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003568 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003569 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003570 return false;
3571 }
3572
3573 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3574 if (wback && BitIsClear (registers, n))
3575 {
Caroline Tice85aab332011-02-08 23:56:10 +00003576 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3577 if (!success)
3578 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003579
3580 offset = addr_byte_size * BitCount (registers);
3581 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003582 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003583 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3585 return false;
3586 }
3587
3588 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3589 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003590 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003591 }
3592 return true;
3593}
Caroline Tice0b29e242011-02-08 23:16:02 +00003594
Johnny Chenef21b592011-02-10 01:52:38 +00003595// Load Register (immediate) calculates an address from a base register value and
3596// an immediate offset, loads a word from memory, and writes to a register.
3597// LDR (immediate, Thumb)
3598bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003599EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003600{
3601#if 0
3602 // ARM pseudo code...
3603 if (ConditionPassed())
3604 {
3605 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3606 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3607 address = if index then offset_addr else R[n];
3608 data = MemU[address,4];
3609 if wback then R[n] = offset_addr;
3610 if t == 15 then
3611 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3612 elsif UnalignedSupport() || address<1:0> = '00' then
3613 R[t] = data;
3614 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3615 }
3616#endif
3617
3618 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003619
Greg Clayton7bc39082011-03-24 23:53:38 +00003620 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003621 {
3622 uint32_t Rt; // the destination register
3623 uint32_t Rn; // the base register
3624 uint32_t imm32; // the immediate offset used to form the address
3625 addr_t offset_addr; // the offset address
3626 addr_t address; // the calculated address
3627 uint32_t data; // the literal data value from memory load
3628 bool add, index, wback;
3629 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003630 case eEncodingT1:
3631 Rt = Bits32(opcode, 5, 3);
3632 Rn = Bits32(opcode, 2, 0);
3633 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3634 // index = TRUE; add = TRUE; wback = FALSE
3635 add = true;
3636 index = true;
3637 wback = false;
3638
3639 break;
3640
3641 case eEncodingT2:
3642 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3643 Rt = Bits32 (opcode, 10, 8);
3644 Rn = 13;
3645 imm32 = Bits32 (opcode, 7, 0) << 2;
3646
3647 // index = TRUE; add = TRUE; wback = FALSE;
3648 index = true;
3649 add = true;
3650 wback = false;
3651
3652 break;
3653
3654 case eEncodingT3:
3655 // if Rn == ‘1111’ then SEE LDR (literal);
3656 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3657 Rt = Bits32 (opcode, 15, 12);
3658 Rn = Bits32 (opcode, 19, 16);
3659 imm32 = Bits32 (opcode, 11, 0);
3660
3661 // index = TRUE; add = TRUE; wback = FALSE;
3662 index = true;
3663 add = true;
3664 wback = false;
3665
3666 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3667 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3668 return false;
3669
3670 break;
3671
3672 case eEncodingT4:
3673 // if Rn == ‘1111’ then SEE LDR (literal);
3674 // if P == ‘1’ && U == ‘1’ && W == ‘0’ then SEE LDRT;
3675 // if Rn == ‘1101’ && P == ‘0’ && U == ‘1’ && W == ‘1’ && imm8 == ‘00000100’ then SEE POP;
3676 // if P == ‘0’ && W == ‘0’ then UNDEFINED;
3677 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3678 return false;
3679
3680 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3681 Rt = Bits32 (opcode, 15, 12);
3682 Rn = Bits32 (opcode, 19, 16);
3683 imm32 = Bits32 (opcode, 7, 0);
3684
3685 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
3686 index = BitIsSet (opcode, 10);
3687 add = BitIsSet (opcode, 9);
3688 wback = BitIsSet (opcode, 8);
3689
3690 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3691 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3692 return false;
3693
3694 break;
3695
3696 default:
3697 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003698 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003699 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003700 if (!success)
3701 return false;
3702 if (add)
3703 offset_addr = base + imm32;
3704 else
3705 offset_addr = base - imm32;
3706
3707 address = (index ? offset_addr : base);
3708
Caroline Ticebaf1f642011-03-24 19:23:45 +00003709 Register base_reg;
3710 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003711 if (wback)
3712 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003713 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003714 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3715 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003716
Johnny Chenef21b592011-02-10 01:52:38 +00003717 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3718 return false;
3719 }
3720
3721 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003722 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003723 context.type = EmulateInstruction::eContextRegisterLoad;
3724 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003725
3726 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003727 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003728 if (!success)
3729 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003730
3731 if (Rt == 15)
3732 {
3733 if (Bits32(address, 1, 0) == 0)
3734 {
Johnny Chen668b4512011-02-15 21:08:58 +00003735 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003736 return false;
3737 }
3738 else
3739 return false;
3740 }
3741 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3742 {
3743 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3744 return false;
3745 }
3746 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003747 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003748 }
3749 return true;
3750}
3751
Caroline Ticeaf556562011-02-15 18:42:15 +00003752// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3753// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3754// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003755bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003756EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003757{
3758#if 0
3759 if ConditionPassed() then
3760 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3761 address = R[n];
3762
3763 for i = 0 to 14
3764 if registers<i> == ’1’ then
3765 if i == n && wback && i != LowestSetBit(registers) then
3766 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3767 else
3768 MemA[address,4] = R[i];
3769 address = address + 4;
3770
3771 if registers<15> == ’1’ then // Only possible for encoding A1
3772 MemA[address,4] = PCStoreValue();
3773 if wback then R[n] = R[n] + 4*BitCount(registers);
3774#endif
3775
3776 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003777
Greg Clayton7bc39082011-03-24 23:53:38 +00003778 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003779 {
3780 uint32_t n;
3781 uint32_t registers = 0;
3782 bool wback;
3783 const uint32_t addr_byte_size = GetAddressByteSize();
3784
3785 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3786 switch (encoding)
3787 {
3788 case eEncodingT1:
3789 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3790 n = Bits32 (opcode, 10, 8);
3791 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003792 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003793 wback = true;
3794
3795 // if BitCount(registers) < 1 then UNPREDICTABLE;
3796 if (BitCount (registers) < 1)
3797 return false;
3798
3799 break;
3800
3801 case eEncodingT2:
3802 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3803 n = Bits32 (opcode, 19, 16);
3804 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003805 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003806 wback = BitIsSet (opcode, 21);
3807
3808 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3809 if ((n == 15) || (BitCount (registers) < 2))
3810 return false;
3811
3812 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3813 if (wback && BitIsSet (registers, n))
3814 return false;
3815
3816 break;
3817
3818 case eEncodingA1:
3819 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3820 n = Bits32 (opcode, 19, 16);
3821 registers = Bits32 (opcode, 15, 0);
3822 wback = BitIsSet (opcode, 21);
3823
3824 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3825 if ((n == 15) || (BitCount (registers) < 1))
3826 return false;
3827
3828 break;
3829
3830 default:
3831 return false;
3832 }
3833
3834 // address = R[n];
3835 int32_t offset = 0;
3836 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3837 if (!success)
3838 return false;
3839
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003840 EmulateInstruction::Context context;
3841 context.type = EmulateInstruction::eContextRegisterStore;
3842 Register base_reg;
3843 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003844
3845 // for i = 0 to 14
3846 for (int i = 0; i < 14; ++i)
3847 {
3848 int lowest_set_bit = 14;
3849 // if registers<i> == ’1’ then
3850 if (BitIsSet (registers, i))
3851 {
3852 if (i < lowest_set_bit)
3853 lowest_set_bit = i;
3854 // if i == n && wback && i != LowestSetBit(registers) then
3855 if ((i == n) && wback && (i != lowest_set_bit))
3856 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3857 WriteBits32UnknownToMemory (address + offset);
3858 else
3859 {
3860 // MemA[address,4] = R[i];
3861 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3862 if (!success)
3863 return false;
3864
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003865 Register data_reg;
3866 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3867 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003868 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003869 return false;
3870 }
3871
3872 // address = address + 4;
3873 offset += addr_byte_size;
3874 }
3875 }
3876
3877 // if registers<15> == ’1’ then // Only possible for encoding A1
3878 // MemA[address,4] = PCStoreValue();
3879 if (BitIsSet (registers, 15))
3880 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003881 Register pc_reg;
3882 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3883 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003884 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003885 if (!success)
3886 return false;
3887
Caroline Tice8d681f52011-03-17 23:50:16 +00003888 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003889 return false;
3890 }
3891
3892 // if wback then R[n] = R[n] + 4*BitCount(registers);
3893 if (wback)
3894 {
3895 offset = addr_byte_size * BitCount (registers);
3896 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003897 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003898 addr_t data = address + offset;
3899 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3900 return false;
3901 }
3902 }
3903 return true;
3904}
3905
Caroline Ticeaf556562011-02-15 18:42:15 +00003906// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3907// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3908// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003909bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003910EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00003911{
3912#if 0
3913 if ConditionPassed() then
3914 EncodingSpecificOperations();
3915 address = R[n] - 4*BitCount(registers) + 4;
3916
3917 for i = 0 to 14
3918 if registers<i> == ’1’ then
3919 if i == n && wback && i != LowestSetBit(registers) then
3920 MemA[address,4] = bits(32) UNKNOWN;
3921 else
3922 MemA[address,4] = R[i];
3923 address = address + 4;
3924
3925 if registers<15> == ’1’ then
3926 MemA[address,4] = PCStoreValue();
3927
3928 if wback then R[n] = R[n] - 4*BitCount(registers);
3929#endif
3930
3931 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00003932
Greg Clayton7bc39082011-03-24 23:53:38 +00003933 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00003934 {
3935 uint32_t n;
3936 uint32_t registers = 0;
3937 bool wback;
3938 const uint32_t addr_byte_size = GetAddressByteSize();
3939
3940 // EncodingSpecificOperations();
3941 switch (encoding)
3942 {
3943 case eEncodingA1:
3944 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3945 n = Bits32 (opcode, 19, 16);
3946 registers = Bits32 (opcode, 15, 0);
3947 wback = BitIsSet (opcode, 21);
3948
3949 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3950 if ((n == 15) || (BitCount (registers) < 1))
3951 return false;
3952 break;
3953 default:
3954 return false;
3955 }
3956
3957 // address = R[n] - 4*BitCount(registers) + 4;
3958 int32_t offset = 0;
3959 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3960 if (!success)
3961 return false;
3962
3963 address = address - (addr_byte_size * BitCount (registers)) + 4;
3964
3965 EmulateInstruction::Context context;
3966 context.type = EmulateInstruction::eContextRegisterStore;
3967 Register base_reg;
3968 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3969
3970 // for i = 0 to 14
3971 for (int i = 0; i < 14; ++i)
3972 {
3973 int lowest_bit_set = 14;
3974 // if registers<i> == ’1’ then
3975 if (BitIsSet (registers, i))
3976 {
3977 if (i < lowest_bit_set)
3978 lowest_bit_set = i;
3979 //if i == n && wback && i != LowestSetBit(registers) then
3980 if ((i == n) && wback && (i != lowest_bit_set))
3981 // MemA[address,4] = bits(32) UNKNOWN;
3982 WriteBits32UnknownToMemory (address + offset);
3983 else
3984 {
3985 // MemA[address,4] = R[i];
3986 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3987 if (!success)
3988 return false;
3989
3990 Register data_reg;
3991 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3992 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003993 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003994 return false;
3995 }
3996
3997 // address = address + 4;
3998 offset += addr_byte_size;
3999 }
4000 }
4001
4002 // if registers<15> == ’1’ then
4003 // MemA[address,4] = PCStoreValue();
4004 if (BitIsSet (registers, 15))
4005 {
4006 Register pc_reg;
4007 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4008 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004009 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004010 if (!success)
4011 return false;
4012
Caroline Tice8d681f52011-03-17 23:50:16 +00004013 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004014 return false;
4015 }
4016
4017 // if wback then R[n] = R[n] - 4*BitCount(registers);
4018 if (wback)
4019 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004020 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004021 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4022 context.SetImmediateSigned (offset);
4023 addr_t data = address + offset;
4024 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4025 return false;
4026 }
4027 }
4028 return true;
4029}
4030
Caroline Ticeaf556562011-02-15 18:42:15 +00004031// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4032// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4033// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004034bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004035EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004036{
4037#if 0
4038 if ConditionPassed() then
4039 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4040 address = R[n] - 4*BitCount(registers);
4041
4042 for i = 0 to 14
4043 if registers<i> == ’1’ then
4044 if i == n && wback && i != LowestSetBit(registers) then
4045 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4046 else
4047 MemA[address,4] = R[i];
4048 address = address + 4;
4049
4050 if registers<15> == ’1’ then // Only possible for encoding A1
4051 MemA[address,4] = PCStoreValue();
4052
4053 if wback then R[n] = R[n] - 4*BitCount(registers);
4054#endif
4055
4056
4057 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004058
Greg Clayton7bc39082011-03-24 23:53:38 +00004059 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004060 {
4061 uint32_t n;
4062 uint32_t registers = 0;
4063 bool wback;
4064 const uint32_t addr_byte_size = GetAddressByteSize();
4065
4066 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4067 switch (encoding)
4068 {
4069 case eEncodingT1:
4070 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4071 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4072 {
4073 // See PUSH
4074 }
4075 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4076 n = Bits32 (opcode, 19, 16);
4077 registers = Bits32 (opcode, 15, 0);
4078 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4079 wback = BitIsSet (opcode, 21);
4080 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4081 if ((n == 15) || BitCount (registers) < 2)
4082 return false;
4083 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4084 if (wback && BitIsSet (registers, n))
4085 return false;
4086 break;
4087
4088 case eEncodingA1:
4089 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4090 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4091 {
4092 // See Push
4093 }
4094 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4095 n = Bits32 (opcode, 19, 16);
4096 registers = Bits32 (opcode, 15, 0);
4097 wback = BitIsSet (opcode, 21);
4098 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4099 if ((n == 15) || BitCount (registers) < 1)
4100 return false;
4101 break;
4102
4103 default:
4104 return false;
4105 }
4106
4107 // address = R[n] - 4*BitCount(registers);
4108
4109 int32_t offset = 0;
4110 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4111 if (!success)
4112 return false;
4113
4114 address = address - (addr_byte_size * BitCount (registers));
4115
4116 EmulateInstruction::Context context;
4117 context.type = EmulateInstruction::eContextRegisterStore;
4118 Register base_reg;
4119 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4120
4121 // for i = 0 to 14
4122 for (int i = 0; i < 14; ++i)
4123 {
4124 uint32_t lowest_set_bit = 14;
4125 // if registers<i> == ’1’ then
4126 if (BitIsSet (registers, i))
4127 {
4128 if (i < lowest_set_bit)
4129 lowest_set_bit = i;
4130 // if i == n && wback && i != LowestSetBit(registers) then
4131 if ((i == n) && wback && (i != lowest_set_bit))
4132 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4133 WriteBits32UnknownToMemory (address + offset);
4134 else
4135 {
4136 // MemA[address,4] = R[i];
4137 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4138 if (!success)
4139 return false;
4140
4141 Register data_reg;
4142 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4143 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004144 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004145 return false;
4146 }
4147
4148 // address = address + 4;
4149 offset += addr_byte_size;
4150 }
4151 }
4152
4153 // if registers<15> == ’1’ then // Only possible for encoding A1
4154 // MemA[address,4] = PCStoreValue();
4155 if (BitIsSet (registers, 15))
4156 {
4157 Register pc_reg;
4158 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4159 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004160 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004161 if (!success)
4162 return false;
4163
Caroline Tice8d681f52011-03-17 23:50:16 +00004164 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004165 return false;
4166 }
4167
4168 // if wback then R[n] = R[n] - 4*BitCount(registers);
4169 if (wback)
4170 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004171 offset = (addr_byte_size * BitCount (registers)) * -1;
4172 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4173 context.SetImmediateSigned (offset);
4174 addr_t data = address + offset;
4175 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4176 return false;
4177 }
4178 }
4179 return true;
4180}
4181
4182// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4183// from a base register. The consecutive memory locations start just above this address, and the address of the last
4184// of those locations can optionally be written back to the base register.
4185bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004186EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004187{
4188#if 0
4189 if ConditionPassed() then
4190 EncodingSpecificOperations();
4191 address = R[n] + 4;
4192
4193 for i = 0 to 14
4194 if registers<i> == ’1’ then
4195 if i == n && wback && i != LowestSetBit(registers) then
4196 MemA[address,4] = bits(32) UNKNOWN;
4197 else
4198 MemA[address,4] = R[i];
4199 address = address + 4;
4200
4201 if registers<15> == ’1’ then
4202 MemA[address,4] = PCStoreValue();
4203
4204 if wback then R[n] = R[n] + 4*BitCount(registers);
4205#endif
4206
4207 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004208
Greg Clayton7bc39082011-03-24 23:53:38 +00004209 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004210 {
4211 uint32_t n;
4212 uint32_t registers = 0;
4213 bool wback;
4214 const uint32_t addr_byte_size = GetAddressByteSize();
4215
4216 // EncodingSpecificOperations();
4217 switch (encoding)
4218 {
4219 case eEncodingA1:
4220 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4221 n = Bits32 (opcode, 19, 16);
4222 registers = Bits32 (opcode, 15, 0);
4223 wback = BitIsSet (opcode, 21);
4224
4225 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4226 if ((n == 15) && (BitCount (registers) < 1))
4227 return false;
4228 break;
4229 default:
4230 return false;
4231 }
4232 // address = R[n] + 4;
4233
4234 int32_t offset = 0;
4235 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4236 if (!success)
4237 return false;
4238
4239 address = address + addr_byte_size;
4240
4241 EmulateInstruction::Context context;
4242 context.type = EmulateInstruction::eContextRegisterStore;
4243 Register base_reg;
4244 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4245
4246 uint32_t lowest_set_bit = 14;
4247 // for i = 0 to 14
4248 for (int i = 0; i < 14; ++i)
4249 {
4250 // if registers<i> == ’1’ then
4251 if (BitIsSet (registers, i))
4252 {
4253 if (i < lowest_set_bit)
4254 lowest_set_bit = i;
4255 // if i == n && wback && i != LowestSetBit(registers) then
4256 if ((i == n) && wback && (i != lowest_set_bit))
4257 // MemA[address,4] = bits(32) UNKNOWN;
4258 WriteBits32UnknownToMemory (address + offset);
4259 // else
4260 else
4261 {
4262 // MemA[address,4] = R[i];
4263 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4264 if (!success)
4265 return false;
4266
4267 Register data_reg;
4268 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4269 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004270 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004271 return false;
4272 }
4273
4274 // address = address + 4;
4275 offset += addr_byte_size;
4276 }
4277 }
4278
4279 // if registers<15> == ’1’ then
4280 // MemA[address,4] = PCStoreValue();
4281 if (BitIsSet (registers, 15))
4282 {
4283 Register pc_reg;
4284 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4285 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004286 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004287 if (!success)
4288 return false;
4289
Caroline Tice8d681f52011-03-17 23:50:16 +00004290 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004291 return false;
4292 }
4293
4294 // if wback then R[n] = R[n] + 4*BitCount(registers);
4295 if (wback)
4296 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004297 offset = addr_byte_size * BitCount (registers);
4298 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4299 context.SetImmediateSigned (offset);
4300 addr_t data = address + offset;
4301 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4302 return false;
4303 }
4304 }
4305 return true;
4306}
Caroline Tice7fac8572011-02-15 22:53:54 +00004307
4308// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4309// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4310bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004311EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004312{
4313#if 0
4314 if ConditionPassed() then
4315 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4316 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4317 address = if index then offset_addr else R[n];
4318 if UnalignedSupport() || address<1:0> == ’00’ then
4319 MemU[address,4] = R[t];
4320 else // Can only occur before ARMv7
4321 MemU[address,4] = bits(32) UNKNOWN;
4322 if wback then R[n] = offset_addr;
4323#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004324
Caroline Tice7fac8572011-02-15 22:53:54 +00004325 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004326
Greg Clayton7bc39082011-03-24 23:53:38 +00004327 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004328 {
4329 const uint32_t addr_byte_size = GetAddressByteSize();
4330
4331 uint32_t t;
4332 uint32_t n;
4333 uint32_t imm32;
4334 bool index;
4335 bool add;
4336 bool wback;
4337 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4338 switch (encoding)
4339 {
4340 case eEncodingT1:
4341 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4342 t = Bits32 (opcode, 2, 0);
4343 n = Bits32 (opcode, 5, 3);
4344 imm32 = Bits32 (opcode, 10, 6) << 2;
4345
4346 // index = TRUE; add = TRUE; wback = FALSE;
4347 index = true;
4348 add = false;
4349 wback = false;
4350 break;
4351
4352 case eEncodingT2:
4353 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4354 t = Bits32 (opcode, 10, 8);
4355 n = 13;
4356 imm32 = Bits32 (opcode, 7, 0) << 2;
4357
4358 // index = TRUE; add = TRUE; wback = FALSE;
4359 index = true;
4360 add = true;
4361 wback = false;
4362 break;
4363
4364 case eEncodingT3:
4365 // if Rn == ’1111’ then UNDEFINED;
4366 if (Bits32 (opcode, 19, 16) == 15)
4367 return false;
4368
4369 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4370 t = Bits32 (opcode, 15, 12);
4371 n = Bits32 (opcode, 19, 16);
4372 imm32 = Bits32 (opcode, 11, 0);
4373
4374 // index = TRUE; add = TRUE; wback = FALSE;
4375 index = true;
4376 add = true;
4377 wback = false;
4378
4379 // if t == 15 then UNPREDICTABLE;
4380 if (t == 15)
4381 return false;
4382 break;
4383
4384 case eEncodingT4:
4385 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4386 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4387 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4388 if ((Bits32 (opcode, 19, 16) == 15)
4389 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4390 return false;
4391
4392 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4393 t = Bits32 (opcode, 15, 12);
4394 n = Bits32 (opcode, 19, 16);
4395 imm32 = Bits32 (opcode, 7, 0);
4396
4397 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4398 index = BitIsSet (opcode, 10);
4399 add = BitIsSet (opcode, 9);
4400 wback = BitIsSet (opcode, 8);
4401
4402 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4403 if ((t == 15) || (wback && (n == t)))
4404 return false;
4405 break;
4406
4407 default:
4408 return false;
4409 }
4410
4411 addr_t offset_addr;
4412 addr_t address;
4413
4414 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004415 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004416 if (!success)
4417 return false;
4418
4419 if (add)
4420 offset_addr = base_address + imm32;
4421 else
4422 offset_addr = base_address - imm32;
4423
4424 // address = if index then offset_addr else R[n];
4425 if (index)
4426 address = offset_addr;
4427 else
4428 address = base_address;
4429
4430 EmulateInstruction::Context context;
4431 context.type = eContextRegisterStore;
4432 Register base_reg;
4433 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4434
4435 // if UnalignedSupport() || address<1:0> == ’00’ then
4436 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4437 {
4438 // MemU[address,4] = R[t];
4439 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4440 if (!success)
4441 return false;
4442
4443 Register data_reg;
4444 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4445 int32_t offset = address - base_address;
4446 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004447 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004448 return false;
4449 }
4450 else
4451 {
4452 // MemU[address,4] = bits(32) UNKNOWN;
4453 WriteBits32UnknownToMemory (address);
4454 }
4455
4456 // if wback then R[n] = offset_addr;
4457 if (wback)
4458 {
4459 context.type = eContextRegisterLoad;
4460 context.SetAddress (offset_addr);
4461 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4462 return false;
4463 }
4464 }
4465 return true;
4466}
Caroline Ticeaf556562011-02-15 18:42:15 +00004467
Caroline Tice3fd63e92011-02-16 00:33:43 +00004468// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4469// word from a register to memory. The offset register value can optionally be shifted.
4470bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004471EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004472{
4473#if 0
4474 if ConditionPassed() then
4475 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4476 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4477 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4478 address = if index then offset_addr else R[n];
4479 if t == 15 then // Only possible for encoding A1
4480 data = PCStoreValue();
4481 else
4482 data = R[t];
4483 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4484 MemU[address,4] = data;
4485 else // Can only occur before ARMv7
4486 MemU[address,4] = bits(32) UNKNOWN;
4487 if wback then R[n] = offset_addr;
4488#endif
4489
4490 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004491
Greg Clayton7bc39082011-03-24 23:53:38 +00004492 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004493 {
4494 const uint32_t addr_byte_size = GetAddressByteSize();
4495
4496 uint32_t t;
4497 uint32_t n;
4498 uint32_t m;
4499 ARM_ShifterType shift_t;
4500 uint32_t shift_n;
4501 bool index;
4502 bool add;
4503 bool wback;
4504
4505 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4506 switch (encoding)
4507 {
4508 case eEncodingT1:
4509 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4510 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4511 t = Bits32 (opcode, 2, 0);
4512 n = Bits32 (opcode, 5, 3);
4513 m = Bits32 (opcode, 8, 6);
4514
4515 // index = TRUE; add = TRUE; wback = FALSE;
4516 index = true;
4517 add = true;
4518 wback = false;
4519
4520 // (shift_t, shift_n) = (SRType_LSL, 0);
4521 shift_t = SRType_LSL;
4522 shift_n = 0;
4523 break;
4524
4525 case eEncodingT2:
4526 // if Rn == ’1111’ then UNDEFINED;
4527 if (Bits32 (opcode, 19, 16) == 15)
4528 return false;
4529
4530 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4531 t = Bits32 (opcode, 15, 12);
4532 n = Bits32 (opcode, 19, 16);
4533 m = Bits32 (opcode, 3, 0);
4534
4535 // index = TRUE; add = TRUE; wback = FALSE;
4536 index = true;
4537 add = true;
4538 wback = false;
4539
4540 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4541 shift_t = SRType_LSL;
4542 shift_n = Bits32 (opcode, 5, 4);
4543
4544 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4545 if ((t == 15) || (BadReg (m)))
4546 return false;
4547 break;
4548
4549 case eEncodingA1:
4550 {
4551 // if P == ’0’ && W == ’1’ then SEE STRT;
4552 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4553 t = Bits32 (opcode, 15, 12);
4554 n = Bits32 (opcode, 19, 16);
4555 m = Bits32 (opcode, 3, 0);
4556
4557 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4558 index = BitIsSet (opcode, 24);
4559 add = BitIsSet (opcode, 23);
4560 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4561
4562 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4563 uint32_t typ = Bits32 (opcode, 6, 5);
4564 uint32_t imm5 = Bits32 (opcode, 11, 7);
4565 shift_n = DecodeImmShift(typ, imm5, shift_t);
4566
4567 // if m == 15 then UNPREDICTABLE;
4568 if (m == 15)
4569 return false;
4570
4571 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4572 if (wback && ((n == 15) || (n == t)))
4573 return false;
4574
4575 break;
4576 }
4577 default:
4578 return false;
4579 }
4580
4581 addr_t offset_addr;
4582 addr_t address;
4583 int32_t offset = 0;
4584
4585 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4586 if (!success)
4587 return false;
4588
4589 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4590 if (!success)
4591 return false;
4592
4593 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004594 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004595
4596 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4597 if (add)
4598 offset_addr = base_address + offset;
4599 else
4600 offset_addr = base_address - offset;
4601
4602 // address = if index then offset_addr else R[n];
4603 if (index)
4604 address = offset_addr;
4605 else
4606 address = base_address;
4607
4608 uint32_t data;
4609 // if t == 15 then // Only possible for encoding A1
4610 if (t == 15)
4611 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004612 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004613 else
4614 // data = R[t];
4615 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4616
4617 if (!success)
4618 return false;
4619
4620 EmulateInstruction::Context context;
4621 context.type = eContextRegisterStore;
4622
4623 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4624 if (UnalignedSupport ()
4625 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4626 || CurrentInstrSet() == eModeARM)
4627 {
4628 // MemU[address,4] = data;
4629
4630 Register base_reg;
4631 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4632
4633 Register data_reg;
4634 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4635
4636 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004637 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004638 return false;
4639
4640 }
4641 else
4642 // MemU[address,4] = bits(32) UNKNOWN;
4643 WriteBits32UnknownToMemory (address);
4644
4645 // if wback then R[n] = offset_addr;
4646 if (wback)
4647 {
4648 context.type = eContextRegisterLoad;
4649 context.SetAddress (offset_addr);
4650 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4651 return false;
4652 }
4653
4654 }
4655 return true;
4656}
Caroline Tice73a29de2011-02-16 20:22:22 +00004657
4658bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004659EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004660{
4661#if 0
4662 if ConditionPassed() then
4663 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4664 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4665 address = if index then offset_addr else R[n];
4666 MemU[address,1] = R[t]<7:0>;
4667 if wback then R[n] = offset_addr;
4668#endif
4669
4670
4671 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004672
Greg Clayton7bc39082011-03-24 23:53:38 +00004673 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004674 {
4675 uint32_t t;
4676 uint32_t n;
4677 uint32_t imm32;
4678 bool index;
4679 bool add;
4680 bool wback;
4681 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4682 switch (encoding)
4683 {
4684 case eEncodingT1:
4685 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4686 t = Bits32 (opcode, 2, 0);
4687 n = Bits32 (opcode, 5, 3);
4688 imm32 = Bits32 (opcode, 10, 6);
4689
4690 // index = TRUE; add = TRUE; wback = FALSE;
4691 index = true;
4692 add = true;
4693 wback = false;
4694 break;
4695
4696 case eEncodingT2:
4697 // if Rn == ’1111’ then UNDEFINED;
4698 if (Bits32 (opcode, 19, 16) == 15)
4699 return false;
4700
4701 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4702 t = Bits32 (opcode, 15, 12);
4703 n = Bits32 (opcode, 19, 16);
4704 imm32 = Bits32 (opcode, 11, 0);
4705
4706 // index = TRUE; add = TRUE; wback = FALSE;
4707 index = true;
4708 add = true;
4709 wback = false;
4710
4711 // if BadReg(t) then UNPREDICTABLE;
4712 if (BadReg (t))
4713 return false;
4714 break;
4715
4716 case eEncodingT3:
4717 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4718 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4719 if (Bits32 (opcode, 19, 16) == 15)
4720 return false;
4721
4722 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4723 t = Bits32 (opcode, 15, 12);
4724 n = Bits32 (opcode, 19, 16);
4725 imm32 = Bits32 (opcode, 7, 0);
4726
4727 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4728 index = BitIsSet (opcode, 10);
4729 add = BitIsSet (opcode, 9);
4730 wback = BitIsSet (opcode, 8);
4731
4732 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4733 if ((BadReg (t)) || (wback && (n == t)))
4734 return false;
4735 break;
4736
4737 default:
4738 return false;
4739 }
4740
4741 addr_t offset_addr;
4742 addr_t address;
4743 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4744 if (!success)
4745 return false;
4746
4747 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4748 if (add)
4749 offset_addr = base_address + imm32;
4750 else
4751 offset_addr = base_address - imm32;
4752
4753 // address = if index then offset_addr else R[n];
4754 if (index)
4755 address = offset_addr;
4756 else
4757 address = base_address;
4758
Caroline Ticecc96eb52011-02-17 19:20:40 +00004759 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004760 Register base_reg;
4761 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4762
4763 Register data_reg;
4764 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4765
4766 EmulateInstruction::Context context;
4767 context.type = eContextRegisterStore;
4768 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4769
4770 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4771 if (!success)
4772 return false;
4773
4774 data = Bits32 (data, 7, 0);
4775
Caroline Ticecc96eb52011-02-17 19:20:40 +00004776 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004777 return false;
4778
4779 // if wback then R[n] = offset_addr;
4780 if (wback)
4781 {
4782 context.type = eContextRegisterLoad;
4783 context.SetAddress (offset_addr);
4784 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4785 return false;
4786 }
4787
4788 }
4789
4790 return true;
4791}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004792
4793// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4794// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4795bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004796EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004797{
4798#if 0
4799 if ConditionPassed() then
4800 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4801 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4802 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4803 address = if index then offset_addr else R[n];
4804 if UnalignedSupport() || address<0> == ’0’ then
4805 MemU[address,2] = R[t]<15:0>;
4806 else // Can only occur before ARMv7
4807 MemU[address,2] = bits(16) UNKNOWN;
4808 if wback then R[n] = offset_addr;
4809#endif
4810
4811 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004812
Greg Clayton7bc39082011-03-24 23:53:38 +00004813 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004814 {
4815 uint32_t t;
4816 uint32_t n;
4817 uint32_t m;
4818 bool index;
4819 bool add;
4820 bool wback;
4821 ARM_ShifterType shift_t;
4822 uint32_t shift_n;
4823
4824 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4825 switch (encoding)
4826 {
4827 case eEncodingT1:
4828 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4829 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4830 t = Bits32 (opcode, 2, 0);
4831 n = Bits32 (opcode, 5, 3);
4832 m = Bits32 (opcode, 8, 6);
4833
4834 // index = TRUE; add = TRUE; wback = FALSE;
4835 index = true;
4836 add = true;
4837 wback = false;
4838
4839 // (shift_t, shift_n) = (SRType_LSL, 0);
4840 shift_t = SRType_LSL;
4841 shift_n = 0;
4842
4843 break;
4844
4845 case eEncodingT2:
4846 // if Rn == ’1111’ then UNDEFINED;
4847 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4848 t = Bits32 (opcode, 15, 12);
4849 n = Bits32 (opcode, 19, 16);
4850 m = Bits32 (opcode, 3, 0);
4851 if (n == 15)
4852 return false;
4853
4854 // index = TRUE; add = TRUE; wback = FALSE;
4855 index = true;
4856 add = true;
4857 wback = false;
4858
4859 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4860 shift_t = SRType_LSL;
4861 shift_n = Bits32 (opcode, 5, 4);
4862
4863 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4864 if (BadReg (t) || BadReg (m))
4865 return false;
4866
4867 break;
4868
4869 case eEncodingA1:
4870 // if P == ’0’ && W == ’1’ then SEE STRHT;
4871 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4872 t = Bits32 (opcode, 15, 12);
4873 n = Bits32 (opcode, 19, 16);
4874 m = Bits32 (opcode, 3, 0);
4875
4876 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4877 index = BitIsSet (opcode, 24);
4878 add = BitIsSet (opcode, 23);
4879 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4880
4881 // (shift_t, shift_n) = (SRType_LSL, 0);
4882 shift_t = SRType_LSL;
4883 shift_n = 0;
4884
4885 // if t == 15 || m == 15 then UNPREDICTABLE;
4886 if ((t == 15) || (m == 15))
4887 return false;
4888
4889 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4890 if (wback && ((n == 15) || (n == t)))
4891 return false;
4892
4893 break;
4894
4895 default:
4896 return false;
4897 }
4898
4899 uint32_t Rm = ReadCoreReg (m, &success);
4900 if (!success)
4901 return false;
4902
4903 uint32_t Rn = ReadCoreReg (n, &success);
4904 if (!success)
4905 return false;
4906
4907 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4908 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4909
4910 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4911 addr_t offset_addr;
4912 if (add)
4913 offset_addr = Rn + offset;
4914 else
4915 offset_addr = Rn - offset;
4916
4917 // address = if index then offset_addr else R[n];
4918 addr_t address;
4919 if (index)
4920 address = offset_addr;
4921 else
4922 address = Rn;
4923
4924 EmulateInstruction::Context context;
4925 context.type = eContextRegisterStore;
4926 Register base_reg;
4927 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4928 Register offset_reg;
4929 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4930
4931 // if UnalignedSupport() || address<0> == ’0’ then
4932 if (UnalignedSupport() || BitIsClear (address, 0))
4933 {
4934 // MemU[address,2] = R[t]<15:0>;
4935 uint32_t Rt = ReadCoreReg (t, &success);
4936 if (!success)
4937 return false;
4938
4939 EmulateInstruction::Context context;
4940 context.type = eContextRegisterStore;
4941 Register base_reg;
4942 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4943 Register offset_reg;
4944 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4945 Register data_reg;
4946 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4947 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
4948
4949 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
4950 return false;
4951 }
4952 else // Can only occur before ARMv7
4953 {
4954 // MemU[address,2] = bits(16) UNKNOWN;
4955 }
4956
4957 // if wback then R[n] = offset_addr;
4958 if (wback)
4959 {
4960 context.type = eContextAdjustBaseRegister;
4961 context.SetAddress (offset_addr);
4962 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4963 return false;
4964 }
4965 }
4966
4967 return true;
4968}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004969
Johnny Chen157b9592011-02-18 21:13:05 +00004970// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4971// and writes the result to the destination register. It can optionally update the condition flags
4972// based on the result.
4973bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004974EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00004975{
4976#if 0
4977 // ARM pseudo code...
4978 if ConditionPassed() then
4979 EncodingSpecificOperations();
4980 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4981 if d == 15 then // Can only occur for ARM encoding
4982 ALUWritePC(result); // setflags is always FALSE here
4983 else
4984 R[d] = result;
4985 if setflags then
4986 APSR.N = result<31>;
4987 APSR.Z = IsZeroBit(result);
4988 APSR.C = carry;
4989 APSR.V = overflow;
4990#endif
4991
4992 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00004993
Greg Clayton7bc39082011-03-24 23:53:38 +00004994 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00004995 {
4996 uint32_t Rd, Rn;
4997 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4998 bool setflags;
4999 switch (encoding)
5000 {
5001 case eEncodingT1:
5002 Rd = Bits32(opcode, 11, 8);
5003 Rn = Bits32(opcode, 19, 16);
5004 setflags = BitIsSet(opcode, 20);
5005 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5006 if (BadReg(Rd) || BadReg(Rn))
5007 return false;
5008 break;
5009 case eEncodingA1:
5010 Rd = Bits32(opcode, 15, 12);
5011 Rn = Bits32(opcode, 19, 16);
5012 setflags = BitIsSet(opcode, 20);
5013 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5014 // TODO: Emulate SUBS PC, LR and related instructions.
5015 if (Rd == 15 && setflags)
5016 return false;
5017 break;
5018 default:
5019 return false;
5020 }
5021
5022 // Read the first operand.
5023 int32_t val1 = ReadCoreReg(Rn, &success);
5024 if (!success)
5025 return false;
5026
5027 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5028
5029 EmulateInstruction::Context context;
5030 context.type = EmulateInstruction::eContextImmediate;
5031 context.SetNoArgs ();
5032
5033 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5034 return false;
5035 }
5036 return true;
5037}
5038
5039// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5040// register value, and writes the result to the destination register. It can optionally update the
5041// condition flags based on the result.
5042bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005043EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005044{
5045#if 0
5046 // ARM pseudo code...
5047 if ConditionPassed() then
5048 EncodingSpecificOperations();
5049 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5050 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5051 if d == 15 then // Can only occur for ARM encoding
5052 ALUWritePC(result); // setflags is always FALSE here
5053 else
5054 R[d] = result;
5055 if setflags then
5056 APSR.N = result<31>;
5057 APSR.Z = IsZeroBit(result);
5058 APSR.C = carry;
5059 APSR.V = overflow;
5060#endif
5061
5062 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005063
Greg Clayton7bc39082011-03-24 23:53:38 +00005064 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005065 {
5066 uint32_t Rd, Rn, Rm;
5067 ARM_ShifterType shift_t;
5068 uint32_t shift_n; // the shift applied to the value read from Rm
5069 bool setflags;
5070 switch (encoding)
5071 {
5072 case eEncodingT1:
5073 Rd = Rn = Bits32(opcode, 2, 0);
5074 Rm = Bits32(opcode, 5, 3);
5075 setflags = !InITBlock();
5076 shift_t = SRType_LSL;
5077 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005078 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005079 case eEncodingT2:
5080 Rd = Bits32(opcode, 11, 8);
5081 Rn = Bits32(opcode, 19, 16);
5082 Rm = Bits32(opcode, 3, 0);
5083 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005084 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005085 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5086 return false;
5087 break;
5088 case eEncodingA1:
5089 Rd = Bits32(opcode, 15, 12);
5090 Rn = Bits32(opcode, 19, 16);
5091 Rm = Bits32(opcode, 3, 0);
5092 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005093 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005094 // TODO: Emulate SUBS PC, LR and related instructions.
5095 if (Rd == 15 && setflags)
5096 return false;
5097 break;
5098 default:
5099 return false;
5100 }
5101
5102 // Read the first operand.
5103 int32_t val1 = ReadCoreReg(Rn, &success);
5104 if (!success)
5105 return false;
5106
5107 // Read the second operand.
5108 int32_t val2 = ReadCoreReg(Rm, &success);
5109 if (!success)
5110 return false;
5111
5112 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5113 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5114
5115 EmulateInstruction::Context context;
5116 context.type = EmulateInstruction::eContextImmediate;
5117 context.SetNoArgs ();
5118
5119 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5120 return false;
5121 }
5122 return true;
5123}
5124
Johnny Chena695f952011-02-23 21:24:25 +00005125// This instruction adds an immediate value to the PC value to form a PC-relative address,
5126// and writes the result to the destination register.
5127bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005128EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005129{
5130#if 0
5131 // ARM pseudo code...
5132 if ConditionPassed() then
5133 EncodingSpecificOperations();
5134 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5135 if d == 15 then // Can only occur for ARM encodings
5136 ALUWritePC(result);
5137 else
5138 R[d] = result;
5139#endif
5140
5141 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005142
Greg Clayton7bc39082011-03-24 23:53:38 +00005143 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005144 {
5145 uint32_t Rd;
5146 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5147 bool add;
5148 switch (encoding)
5149 {
5150 case eEncodingT1:
5151 Rd = Bits32(opcode, 10, 8);
5152 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5153 break;
5154 case eEncodingT2:
5155 case eEncodingT3:
5156 Rd = Bits32(opcode, 11, 8);
5157 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5158 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5159 if (BadReg(Rd))
5160 return false;
5161 break;
5162 case eEncodingA1:
5163 case eEncodingA2:
5164 Rd = Bits32(opcode, 15, 12);
5165 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5166 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5167 break;
5168 default:
5169 return false;
5170 }
5171
5172 // Read the PC value.
5173 uint32_t pc = ReadCoreReg(PC_REG, &success);
5174 if (!success)
5175 return false;
5176
5177 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5178
5179 EmulateInstruction::Context context;
5180 context.type = EmulateInstruction::eContextImmediate;
5181 context.SetNoArgs ();
5182
5183 if (!WriteCoreReg(context, result, Rd))
5184 return false;
5185 }
5186 return true;
5187}
5188
Johnny Chene97c0d52011-02-18 19:32:20 +00005189// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5190// to the destination register. It can optionally update the condition flags based on the result.
5191bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005192EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005193{
5194#if 0
5195 // ARM pseudo code...
5196 if ConditionPassed() then
5197 EncodingSpecificOperations();
5198 result = R[n] AND imm32;
5199 if d == 15 then // Can only occur for ARM encoding
5200 ALUWritePC(result); // setflags is always FALSE here
5201 else
5202 R[d] = result;
5203 if setflags then
5204 APSR.N = result<31>;
5205 APSR.Z = IsZeroBit(result);
5206 APSR.C = carry;
5207 // APSR.V unchanged
5208#endif
5209
5210 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005211
Greg Clayton7bc39082011-03-24 23:53:38 +00005212 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005213 {
5214 uint32_t Rd, Rn;
5215 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5216 bool setflags;
5217 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5218 switch (encoding)
5219 {
5220 case eEncodingT1:
5221 Rd = Bits32(opcode, 11, 8);
5222 Rn = Bits32(opcode, 19, 16);
5223 setflags = BitIsSet(opcode, 20);
5224 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005225 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005226 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005227 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005228 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5229 return false;
5230 break;
5231 case eEncodingA1:
5232 Rd = Bits32(opcode, 15, 12);
5233 Rn = Bits32(opcode, 19, 16);
5234 setflags = BitIsSet(opcode, 20);
5235 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5236 // TODO: Emulate SUBS PC, LR and related instructions.
5237 if (Rd == 15 && setflags)
5238 return false;
5239 break;
5240 default:
5241 return false;
5242 }
5243
Johnny Chene97c0d52011-02-18 19:32:20 +00005244 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005245 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005246 if (!success)
5247 return false;
5248
5249 uint32_t result = val1 & imm32;
5250
5251 EmulateInstruction::Context context;
5252 context.type = EmulateInstruction::eContextImmediate;
5253 context.SetNoArgs ();
5254
5255 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5256 return false;
5257 }
5258 return true;
5259}
5260
5261// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5262// and writes the result to the destination register. It can optionally update the condition flags
5263// based on the result.
5264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005265EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005266{
5267#if 0
5268 // ARM pseudo code...
5269 if ConditionPassed() then
5270 EncodingSpecificOperations();
5271 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5272 result = R[n] AND shifted;
5273 if d == 15 then // Can only occur for ARM encoding
5274 ALUWritePC(result); // setflags is always FALSE here
5275 else
5276 R[d] = result;
5277 if setflags then
5278 APSR.N = result<31>;
5279 APSR.Z = IsZeroBit(result);
5280 APSR.C = carry;
5281 // APSR.V unchanged
5282#endif
5283
5284 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005285
Greg Clayton7bc39082011-03-24 23:53:38 +00005286 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005287 {
5288 uint32_t Rd, Rn, Rm;
5289 ARM_ShifterType shift_t;
5290 uint32_t shift_n; // the shift applied to the value read from Rm
5291 bool setflags;
5292 uint32_t carry;
5293 switch (encoding)
5294 {
5295 case eEncodingT1:
5296 Rd = Rn = Bits32(opcode, 2, 0);
5297 Rm = Bits32(opcode, 5, 3);
5298 setflags = !InITBlock();
5299 shift_t = SRType_LSL;
5300 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005301 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005302 case eEncodingT2:
5303 Rd = Bits32(opcode, 11, 8);
5304 Rn = Bits32(opcode, 19, 16);
5305 Rm = Bits32(opcode, 3, 0);
5306 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005307 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005308 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005309 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005310 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005311 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5312 return false;
5313 break;
5314 case eEncodingA1:
5315 Rd = Bits32(opcode, 15, 12);
5316 Rn = Bits32(opcode, 19, 16);
5317 Rm = Bits32(opcode, 3, 0);
5318 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005319 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005320 // TODO: Emulate SUBS PC, LR and related instructions.
5321 if (Rd == 15 && setflags)
5322 return false;
5323 break;
5324 default:
5325 return false;
5326 }
5327
Johnny Chene97c0d52011-02-18 19:32:20 +00005328 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005329 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005330 if (!success)
5331 return false;
5332
5333 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005334 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005335 if (!success)
5336 return false;
5337
5338 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5339 uint32_t result = val1 & shifted;
5340
5341 EmulateInstruction::Context context;
5342 context.type = EmulateInstruction::eContextImmediate;
5343 context.SetNoArgs ();
5344
5345 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5346 return false;
5347 }
5348 return true;
5349}
5350
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005351// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5352// immediate value, and writes the result to the destination register. It can optionally update the
5353// condition flags based on the result.
5354bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005355EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005356{
5357#if 0
5358 // ARM pseudo code...
5359 if ConditionPassed() then
5360 EncodingSpecificOperations();
5361 result = R[n] AND NOT(imm32);
5362 if d == 15 then // Can only occur for ARM encoding
5363 ALUWritePC(result); // setflags is always FALSE here
5364 else
5365 R[d] = result;
5366 if setflags then
5367 APSR.N = result<31>;
5368 APSR.Z = IsZeroBit(result);
5369 APSR.C = carry;
5370 // APSR.V unchanged
5371#endif
5372
5373 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005374
Greg Clayton7bc39082011-03-24 23:53:38 +00005375 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005376 {
5377 uint32_t Rd, Rn;
5378 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5379 bool setflags;
5380 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5381 switch (encoding)
5382 {
5383 case eEncodingT1:
5384 Rd = Bits32(opcode, 11, 8);
5385 Rn = Bits32(opcode, 19, 16);
5386 setflags = BitIsSet(opcode, 20);
5387 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5388 if (BadReg(Rd) || BadReg(Rn))
5389 return false;
5390 break;
5391 case eEncodingA1:
5392 Rd = Bits32(opcode, 15, 12);
5393 Rn = Bits32(opcode, 19, 16);
5394 setflags = BitIsSet(opcode, 20);
5395 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5396 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5397 // TODO: Emulate SUBS PC, LR and related instructions.
5398 if (Rd == 15 && setflags)
5399 return false;
5400 break;
5401 default:
5402 return false;
5403 }
5404
5405 // Read the first operand.
5406 uint32_t val1 = ReadCoreReg(Rn, &success);
5407 if (!success)
5408 return false;
5409
5410 uint32_t result = val1 & ~imm32;
5411
5412 EmulateInstruction::Context context;
5413 context.type = EmulateInstruction::eContextImmediate;
5414 context.SetNoArgs ();
5415
5416 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5417 return false;
5418 }
5419 return true;
5420}
5421
5422// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5423// optionally-shifted register value, and writes the result to the destination register.
5424// It can optionally update the condition flags based on the result.
5425bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005426EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005427{
5428#if 0
5429 // ARM pseudo code...
5430 if ConditionPassed() then
5431 EncodingSpecificOperations();
5432 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5433 result = R[n] AND NOT(shifted);
5434 if d == 15 then // Can only occur for ARM encoding
5435 ALUWritePC(result); // setflags is always FALSE here
5436 else
5437 R[d] = result;
5438 if setflags then
5439 APSR.N = result<31>;
5440 APSR.Z = IsZeroBit(result);
5441 APSR.C = carry;
5442 // APSR.V unchanged
5443#endif
5444
5445 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005446
Greg Clayton7bc39082011-03-24 23:53:38 +00005447 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005448 {
5449 uint32_t Rd, Rn, Rm;
5450 ARM_ShifterType shift_t;
5451 uint32_t shift_n; // the shift applied to the value read from Rm
5452 bool setflags;
5453 uint32_t carry;
5454 switch (encoding)
5455 {
5456 case eEncodingT1:
5457 Rd = Rn = Bits32(opcode, 2, 0);
5458 Rm = Bits32(opcode, 5, 3);
5459 setflags = !InITBlock();
5460 shift_t = SRType_LSL;
5461 shift_n = 0;
5462 break;
5463 case eEncodingT2:
5464 Rd = Bits32(opcode, 11, 8);
5465 Rn = Bits32(opcode, 19, 16);
5466 Rm = Bits32(opcode, 3, 0);
5467 setflags = BitIsSet(opcode, 20);
5468 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5469 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5470 return false;
5471 break;
5472 case eEncodingA1:
5473 Rd = Bits32(opcode, 15, 12);
5474 Rn = Bits32(opcode, 19, 16);
5475 Rm = Bits32(opcode, 3, 0);
5476 setflags = BitIsSet(opcode, 20);
5477 shift_n = DecodeImmShiftARM(opcode, shift_t);
5478 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5479 // TODO: Emulate SUBS PC, LR and related instructions.
5480 if (Rd == 15 && setflags)
5481 return false;
5482 break;
5483 default:
5484 return false;
5485 }
5486
5487 // Read the first operand.
5488 uint32_t val1 = ReadCoreReg(Rn, &success);
5489 if (!success)
5490 return false;
5491
5492 // Read the second operand.
5493 uint32_t val2 = ReadCoreReg(Rm, &success);
5494 if (!success)
5495 return false;
5496
5497 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5498 uint32_t result = val1 & ~shifted;
5499
5500 EmulateInstruction::Context context;
5501 context.type = EmulateInstruction::eContextImmediate;
5502 context.SetNoArgs ();
5503
5504 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5505 return false;
5506 }
5507 return true;
5508}
5509
Caroline Tice4d729c52011-02-18 00:55:53 +00005510// 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 +00005511// 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 +00005512bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005513EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005514{
5515#if 0
5516 if ConditionPassed() then
5517 EncodingSpecificOperations();
5518 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5519 address = if index then offset_addr else R[n];
5520 data = MemU[address,4];
5521 if wback then R[n] = offset_addr;
5522 if t == 15 then
5523 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5524 elsif UnalignedSupport() || address<1:0> = ’00’ then
5525 R[t] = data;
5526 else // Can only apply before ARMv7
5527 R[t] = ROR(data, 8*UInt(address<1:0>));
5528#endif
5529
5530 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005531
Greg Clayton7bc39082011-03-24 23:53:38 +00005532 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005533 {
5534 const uint32_t addr_byte_size = GetAddressByteSize();
5535
5536 uint32_t t;
5537 uint32_t n;
5538 uint32_t imm32;
5539 bool index;
5540 bool add;
5541 bool wback;
5542
5543 switch (encoding)
5544 {
5545 case eEncodingA1:
5546 // if Rn == ’1111’ then SEE LDR (literal);
5547 // if P == ’0’ && W == ’1’ then SEE LDRT;
5548 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5549 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5550 t = Bits32 (opcode, 15, 12);
5551 n = Bits32 (opcode, 19, 16);
5552 imm32 = Bits32 (opcode, 11, 0);
5553
5554 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5555 index = BitIsSet (opcode, 24);
5556 add = BitIsSet (opcode, 23);
5557 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5558
5559 // if wback && n == t then UNPREDICTABLE;
5560 if (wback && (n == t))
5561 return false;
5562
5563 break;
5564
5565 default:
5566 return false;
5567 }
5568
5569 addr_t address;
5570 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005571 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005572 if (!success)
5573 return false;
5574
5575 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5576 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005577 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005578 else
5579 offset_addr = base_address - imm32;
5580
5581 // address = if index then offset_addr else R[n];
5582 if (index)
5583 address = offset_addr;
5584 else
5585 address = base_address;
5586
5587 // data = MemU[address,4];
5588
5589 Register base_reg;
5590 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5591
5592 EmulateInstruction::Context context;
5593 context.type = eContextRegisterLoad;
5594 context.SetRegisterPlusOffset (base_reg, address - base_address);
5595
5596 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5597 if (!success)
5598 return false;
5599
5600 // if wback then R[n] = offset_addr;
5601 if (wback)
5602 {
5603 context.type = eContextAdjustBaseRegister;
5604 context.SetAddress (offset_addr);
5605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5606 return false;
5607 }
5608
5609 // if t == 15 then
5610 if (t == 15)
5611 {
5612 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5613 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5614 {
5615 // LoadWritePC (data);
5616 context.type = eContextRegisterLoad;
5617 context.SetRegisterPlusOffset (base_reg, address - base_address);
5618 LoadWritePC (context, data);
5619 }
5620 else
5621 return false;
5622 }
5623 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5624 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5625 {
5626 // R[t] = data;
5627 context.type = eContextRegisterLoad;
5628 context.SetRegisterPlusOffset (base_reg, address - base_address);
5629 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5630 return false;
5631 }
5632 // else // Can only apply before ARMv7
5633 else
5634 {
5635 // R[t] = ROR(data, 8*UInt(address<1:0>));
5636 data = ROR (data, Bits32 (address, 1, 0));
5637 context.type = eContextRegisterLoad;
5638 context.SetImmediate (data);
5639 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5640 return false;
5641 }
5642
5643 }
5644 return true;
5645}
5646
Caroline Ticefe479112011-02-18 18:52:37 +00005647// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5648// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5649bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005650EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005651{
5652#if 0
5653 if ConditionPassed() then
5654 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5655 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5656 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5657 address = if index then offset_addr else R[n];
5658 data = MemU[address,4];
5659 if wback then R[n] = offset_addr;
5660 if t == 15 then
5661 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5662 elsif UnalignedSupport() || address<1:0> = ’00’ then
5663 R[t] = data;
5664 else // Can only apply before ARMv7
5665 if CurrentInstrSet() == InstrSet_ARM then
5666 R[t] = ROR(data, 8*UInt(address<1:0>));
5667 else
5668 R[t] = bits(32) UNKNOWN;
5669#endif
5670
5671 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005672
Greg Clayton7bc39082011-03-24 23:53:38 +00005673 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005674 {
5675 const uint32_t addr_byte_size = GetAddressByteSize();
5676
5677 uint32_t t;
5678 uint32_t n;
5679 uint32_t m;
5680 bool index;
5681 bool add;
5682 bool wback;
5683 ARM_ShifterType shift_t;
5684 uint32_t shift_n;
5685
5686 switch (encoding)
5687 {
5688 case eEncodingT1:
5689 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5690 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5691 t = Bits32 (opcode, 2, 0);
5692 n = Bits32 (opcode, 5, 3);
5693 m = Bits32 (opcode, 8, 6);
5694
5695 // index = TRUE; add = TRUE; wback = FALSE;
5696 index = true;
5697 add = true;
5698 wback = false;
5699
5700 // (shift_t, shift_n) = (SRType_LSL, 0);
5701 shift_t = SRType_LSL;
5702 shift_n = 0;
5703
5704 break;
5705
5706 case eEncodingT2:
5707 // if Rn == ’1111’ then SEE LDR (literal);
5708 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5709 t = Bits32 (opcode, 15, 12);
5710 n = Bits32 (opcode, 19, 16);
5711 m = Bits32 (opcode, 3, 0);
5712
5713 // index = TRUE; add = TRUE; wback = FALSE;
5714 index = true;
5715 add = true;
5716 wback = false;
5717
5718 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5719 shift_t = SRType_LSL;
5720 shift_n = Bits32 (opcode, 5, 4);
5721
5722 // if BadReg(m) then UNPREDICTABLE;
5723 if (BadReg (m))
5724 return false;
5725
5726 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5727 if ((t == 15) && InITBlock() && !LastInITBlock())
5728 return false;
5729
5730 break;
5731
5732 case eEncodingA1:
5733 {
5734 // if P == ’0’ && W == ’1’ then SEE LDRT;
5735 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5736 t = Bits32 (opcode, 15, 12);
5737 n = Bits32 (opcode, 19, 16);
5738 m = Bits32 (opcode, 3, 0);
5739
5740 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5741 index = BitIsSet (opcode, 24);
5742 add = BitIsSet (opcode, 23);
5743 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5744
5745 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5746 uint32_t type = Bits32 (opcode, 6, 5);
5747 uint32_t imm5 = Bits32 (opcode, 11, 7);
5748 shift_n = DecodeImmShift (type, imm5, shift_t);
5749
5750 // if m == 15 then UNPREDICTABLE;
5751 if (m == 15)
5752 return false;
5753
5754 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5755 if (wback && ((n == 15) || (n == t)))
5756 return false;
5757 }
5758 break;
5759
5760
5761 default:
5762 return false;
5763 }
5764
5765 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5766 if (!success)
5767 return false;
5768
5769 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5770 if (!success)
5771 return false;
5772
5773 addr_t offset_addr;
5774 addr_t address;
5775
5776 // 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 +00005777 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005778
5779 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5780 if (add)
5781 offset_addr = Rn + offset;
5782 else
5783 offset_addr = Rn - offset;
5784
5785 // address = if index then offset_addr else R[n];
5786 if (index)
5787 address = offset_addr;
5788 else
5789 address = Rn;
5790
5791 // data = MemU[address,4];
5792 Register base_reg;
5793 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5794
5795 EmulateInstruction::Context context;
5796 context.type = eContextRegisterLoad;
5797 context.SetRegisterPlusOffset (base_reg, address - Rn);
5798
5799 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5800 if (!success)
5801 return false;
5802
5803 // if wback then R[n] = offset_addr;
5804 if (wback)
5805 {
5806 context.type = eContextAdjustBaseRegister;
5807 context.SetAddress (offset_addr);
5808 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5809 return false;
5810 }
5811
5812 // if t == 15 then
5813 if (t == 15)
5814 {
5815 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5816 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5817 {
5818 context.type = eContextRegisterLoad;
5819 context.SetRegisterPlusOffset (base_reg, address - Rn);
5820 LoadWritePC (context, data);
5821 }
5822 else
5823 return false;
5824 }
5825 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5826 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5827 {
5828 // R[t] = data;
5829 context.type = eContextRegisterLoad;
5830 context.SetRegisterPlusOffset (base_reg, address - Rn);
5831 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5832 return false;
5833 }
5834 else // Can only apply before ARMv7
5835 {
5836 // if CurrentInstrSet() == InstrSet_ARM then
5837 if (CurrentInstrSet () == eModeARM)
5838 {
5839 // R[t] = ROR(data, 8*UInt(address<1:0>));
5840 data = ROR (data, Bits32 (address, 1, 0));
5841 context.type = eContextRegisterLoad;
5842 context.SetImmediate (data);
5843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5844 return false;
5845 }
5846 else
5847 {
5848 // R[t] = bits(32) UNKNOWN;
5849 WriteBits32Unknown (t);
5850 }
5851 }
5852 }
5853 return true;
5854}
Caroline Tice21b604b2011-02-18 21:06:04 +00005855
5856// LDRB (immediate, Thumb)
5857bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005858EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005859{
5860#if 0
5861 if ConditionPassed() then
5862 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5863 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5864 address = if index then offset_addr else R[n];
5865 R[t] = ZeroExtend(MemU[address,1], 32);
5866 if wback then R[n] = offset_addr;
5867#endif
5868
5869 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005870
Greg Clayton7bc39082011-03-24 23:53:38 +00005871 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005872 {
5873 uint32_t t;
5874 uint32_t n;
5875 uint32_t imm32;
5876 bool index;
5877 bool add;
5878 bool wback;
5879
5880 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5881 switch (encoding)
5882 {
5883 case eEncodingT1:
5884 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5885 t = Bits32 (opcode, 2, 0);
5886 n = Bits32 (opcode, 5, 3);
5887 imm32 = Bits32 (opcode, 10, 6);
5888
5889 // index = TRUE; add = TRUE; wback = FALSE;
5890 index = true;
5891 add = true;
5892 wback= false;
5893
5894 break;
5895
5896 case eEncodingT2:
5897 // if Rt == ’1111’ then SEE PLD;
5898 // if Rn == ’1111’ then SEE LDRB (literal);
5899 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5900 t = Bits32 (opcode, 15, 12);
5901 n = Bits32 (opcode, 19, 16);
5902 imm32 = Bits32 (opcode, 11, 0);
5903
5904 // index = TRUE; add = TRUE; wback = FALSE;
5905 index = true;
5906 add = true;
5907 wback = false;
5908
5909 // if t == 13 then UNPREDICTABLE;
5910 if (t == 13)
5911 return false;
5912
5913 break;
5914
5915 case eEncodingT3:
5916 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5917 // if Rn == ’1111’ then SEE LDRB (literal);
5918 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5919 // if P == ’0’ && W == ’0’ then UNDEFINED;
5920 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5921 return false;
5922
5923 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5924 t = Bits32 (opcode, 15, 12);
5925 n = Bits32 (opcode, 19, 16);
5926 imm32 = Bits32 (opcode, 7, 0);
5927
5928 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5929 index = BitIsSet (opcode, 10);
5930 add = BitIsSet (opcode, 9);
5931 wback = BitIsSet (opcode, 8);
5932
5933 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5934 if (BadReg (t) || (wback && (n == t)))
5935 return false;
5936
5937 break;
5938
5939 default:
5940 return false;
5941 }
5942
5943 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5944 if (!success)
5945 return false;
5946
5947 addr_t address;
5948 addr_t offset_addr;
5949
5950 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5951 if (add)
5952 offset_addr = Rn + imm32;
5953 else
5954 offset_addr = Rn - imm32;
5955
5956 // address = if index then offset_addr else R[n];
5957 if (index)
5958 address = offset_addr;
5959 else
5960 address = Rn;
5961
5962 // R[t] = ZeroExtend(MemU[address,1], 32);
5963 Register base_reg;
5964 Register data_reg;
5965 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5966 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5967
5968 EmulateInstruction::Context context;
5969 context.type = eContextRegisterLoad;
5970 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5971
5972 uint64_t data = MemURead (context, address, 1, 0, &success);
5973 if (!success)
5974 return false;
5975
5976 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5977 return false;
5978
5979 // if wback then R[n] = offset_addr;
5980 if (wback)
5981 {
5982 context.type = eContextAdjustBaseRegister;
5983 context.SetAddress (offset_addr);
5984 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5985 return false;
5986 }
5987 }
5988 return true;
5989}
Caroline Ticef55261f2011-02-18 22:24:22 +00005990
5991// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5992// zero-extends it to form a 32-bit word and writes it to a register.
5993bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005994EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00005995{
5996#if 0
5997 if ConditionPassed() then
5998 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5999 base = Align(PC,4);
6000 address = if add then (base + imm32) else (base - imm32);
6001 R[t] = ZeroExtend(MemU[address,1], 32);
6002#endif
6003
6004 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006005
Greg Clayton7bc39082011-03-24 23:53:38 +00006006 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006007 {
6008 uint32_t t;
6009 uint32_t imm32;
6010 bool add;
6011 switch (encoding)
6012 {
6013 case eEncodingT1:
6014 // if Rt == ’1111’ then SEE PLD;
6015 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6016 t = Bits32 (opcode, 15, 12);
6017 imm32 = Bits32 (opcode, 11, 0);
6018 add = BitIsSet (opcode, 23);
6019
6020 // if t == 13 then UNPREDICTABLE;
6021 if (t == 13)
6022 return false;
6023
6024 break;
6025
6026 case eEncodingA1:
6027 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6028 t = Bits32 (opcode, 15, 12);
6029 imm32 = Bits32 (opcode, 11, 0);
6030 add = BitIsSet (opcode, 23);
6031
6032 // if t == 15 then UNPREDICTABLE;
6033 if (t == 15)
6034 return false;
6035 break;
6036
6037 default:
6038 return false;
6039 }
6040
6041 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006042 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006043 if (!success)
6044 return false;
6045
6046 uint32_t base = AlignPC (pc_val);
6047
6048 addr_t address;
6049 // address = if add then (base + imm32) else (base - imm32);
6050 if (add)
6051 address = base + imm32;
6052 else
6053 address = base - imm32;
6054
6055 // R[t] = ZeroExtend(MemU[address,1], 32);
6056 EmulateInstruction::Context context;
6057 context.type = eContextRelativeBranchImmediate;
6058 context.SetImmediate (address - base);
6059
6060 uint64_t data = MemURead (context, address, 1, 0, &success);
6061 if (!success)
6062 return false;
6063
6064 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6065 return false;
6066 }
6067 return true;
6068}
Caroline Tice30fec122011-02-18 23:52:21 +00006069
6070// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6071// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6072// optionally be shifted.
6073bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006074EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006075{
6076#if 0
6077 if ConditionPassed() then
6078 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6079 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6080 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6081 address = if index then offset_addr else R[n];
6082 R[t] = ZeroExtend(MemU[address,1],32);
6083 if wback then R[n] = offset_addr;
6084#endif
6085
6086 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006087
Greg Clayton7bc39082011-03-24 23:53:38 +00006088 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006089 {
6090 uint32_t t;
6091 uint32_t n;
6092 uint32_t m;
6093 bool index;
6094 bool add;
6095 bool wback;
6096 ARM_ShifterType shift_t;
6097 uint32_t shift_n;
6098
6099 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6100 switch (encoding)
6101 {
6102 case eEncodingT1:
6103 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6104 t = Bits32 (opcode, 2, 0);
6105 n = Bits32 (opcode, 5, 3);
6106 m = Bits32 (opcode, 8, 6);
6107
6108 // index = TRUE; add = TRUE; wback = FALSE;
6109 index = true;
6110 add = true;
6111 wback = false;
6112
6113 // (shift_t, shift_n) = (SRType_LSL, 0);
6114 shift_t = SRType_LSL;
6115 shift_n = 0;
6116 break;
6117
6118 case eEncodingT2:
6119 // if Rt == ’1111’ then SEE PLD;
6120 // if Rn == ’1111’ then SEE LDRB (literal);
6121 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6122 t = Bits32 (opcode, 15, 12);
6123 n = Bits32 (opcode, 19, 16);
6124 m = Bits32 (opcode, 3, 0);
6125
6126 // index = TRUE; add = TRUE; wback = FALSE;
6127 index = true;
6128 add = true;
6129 wback = false;
6130
6131 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6132 shift_t = SRType_LSL;
6133 shift_n = Bits32 (opcode, 5, 4);
6134
6135 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6136 if ((t == 13) || BadReg (m))
6137 return false;
6138 break;
6139
6140 case eEncodingA1:
6141 {
6142 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6143 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6144 t = Bits32 (opcode, 15, 12);
6145 n = Bits32 (opcode, 19, 16);
6146 m = Bits32 (opcode, 3, 0);
6147
6148 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6149 index = BitIsSet (opcode, 24);
6150 add = BitIsSet (opcode, 23);
6151 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6152
6153 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6154 uint32_t type = Bits32 (opcode, 6, 5);
6155 uint32_t imm5 = Bits32 (opcode, 11, 7);
6156 shift_n = DecodeImmShift (type, imm5, shift_t);
6157
6158 // if t == 15 || m == 15 then UNPREDICTABLE;
6159 if ((t == 15) || (m == 15))
6160 return false;
6161
6162 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6163 if (wback && ((n == 15) || (n == t)))
6164 return false;
6165 }
6166 break;
6167
6168 default:
6169 return false;
6170 }
6171
6172 addr_t offset_addr;
6173 addr_t address;
6174
6175 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6176 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6177 if (!success)
6178 return false;
6179
6180 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6181
6182 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6183 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6184 if (!success)
6185 return false;
6186
6187 if (add)
6188 offset_addr = Rn + offset;
6189 else
6190 offset_addr = Rn - offset;
6191
6192 // address = if index then offset_addr else R[n];
6193 if (index)
6194 address = offset_addr;
6195 else
6196 address = Rn;
6197
6198 // R[t] = ZeroExtend(MemU[address,1],32);
6199 Register base_reg;
6200 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6201
6202 EmulateInstruction::Context context;
6203 context.type = eContextRegisterLoad;
6204 context.SetRegisterPlusOffset (base_reg, address - Rn);
6205
6206 uint64_t data = MemURead (context, address, 1, 0, &success);
6207 if (!success)
6208 return false;
6209
6210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6211 return false;
6212
6213 // if wback then R[n] = offset_addr;
6214 if (wback)
6215 {
6216 context.type = eContextAdjustBaseRegister;
6217 context.SetAddress (offset_addr);
6218 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6219 return false;
6220 }
6221 }
6222 return true;
6223}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006224
6225// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6226// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6227// post-indexed, or pre-indexed addressing.
6228bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006229EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006230{
6231#if 0
6232 if ConditionPassed() then
6233 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6234 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6235 address = if index then offset_addr else R[n];
6236 data = MemU[address,2];
6237 if wback then R[n] = offset_addr;
6238 if UnalignedSupport() || address<0> = ’0’ then
6239 R[t] = ZeroExtend(data, 32);
6240 else // Can only apply before ARMv7
6241 R[t] = bits(32) UNKNOWN;
6242#endif
6243
6244
6245 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006246
Greg Clayton7bc39082011-03-24 23:53:38 +00006247 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006248 {
6249 uint32_t t;
6250 uint32_t n;
6251 uint32_t imm32;
6252 bool index;
6253 bool add;
6254 bool wback;
6255
6256 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6257 switch (encoding)
6258 {
6259 case eEncodingT1:
6260 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6261 t = Bits32 (opcode, 2, 0);
6262 n = Bits32 (opcode, 5, 3);
6263 imm32 = Bits32 (opcode, 10, 6) << 1;
6264
6265 // index = TRUE; add = TRUE; wback = FALSE;
6266 index = true;
6267 add = true;
6268 wback = false;
6269
6270 break;
6271
6272 case eEncodingT2:
6273 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6274 // if Rn == ’1111’ then SEE LDRH (literal);
6275 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6276 t = Bits32 (opcode, 15, 12);
6277 n = Bits32 (opcode, 19, 16);
6278 imm32 = Bits32 (opcode, 11, 0);
6279
6280 // index = TRUE; add = TRUE; wback = FALSE;
6281 index = true;
6282 add = true;
6283 wback = false;
6284
6285 // if t == 13 then UNPREDICTABLE;
6286 if (t == 13)
6287 return false;
6288 break;
6289
6290 case eEncodingT3:
6291 // if Rn == ’1111’ then SEE LDRH (literal);
6292 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6293 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6294 // if P == ’0’ && W == ’0’ then UNDEFINED;
6295 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6296 return false;
6297
6298 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6299 t = Bits32 (opcode, 15, 12);
6300 n = Bits32 (opcode, 19, 16);
6301 imm32 = Bits32 (opcode, 7, 0);
6302
6303 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6304 index = BitIsSet (opcode, 10);
6305 add = BitIsSet (opcode, 9);
6306 wback = BitIsSet (opcode, 8);
6307
6308 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6309 if (BadReg (t) || (wback && (n == t)))
6310 return false;
6311 break;
6312
6313 default:
6314 return false;
6315 }
6316
6317 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6318 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6319 if (!success)
6320 return false;
6321
6322 addr_t offset_addr;
6323 addr_t address;
6324
6325 if (add)
6326 offset_addr = Rn + imm32;
6327 else
6328 offset_addr = Rn - imm32;
6329
6330 // address = if index then offset_addr else R[n];
6331 if (index)
6332 address = offset_addr;
6333 else
6334 address = Rn;
6335
6336 // data = MemU[address,2];
6337 Register base_reg;
6338 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6339
6340 EmulateInstruction::Context context;
6341 context.type = eContextRegisterLoad;
6342 context.SetRegisterPlusOffset (base_reg, address - Rn);
6343
6344 uint64_t data = MemURead (context, address, 2, 0, &success);
6345 if (!success)
6346 return false;
6347
6348 // if wback then R[n] = offset_addr;
6349 if (wback)
6350 {
6351 context.type = eContextAdjustBaseRegister;
6352 context.SetAddress (offset_addr);
6353 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6354 return false;
6355 }
6356
6357 // if UnalignedSupport() || address<0> = ’0’ then
6358 if (UnalignedSupport () || BitIsClear (address, 0))
6359 {
6360 // R[t] = ZeroExtend(data, 32);
6361 context.type = eContextRegisterLoad;
6362 context.SetRegisterPlusOffset (base_reg, address - Rn);
6363 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6364 return false;
6365 }
6366 else // Can only apply before ARMv7
6367 {
6368 // R[t] = bits(32) UNKNOWN;
6369 WriteBits32Unknown (t);
6370 }
6371 }
6372 return true;
6373}
Caroline Ticefe479112011-02-18 18:52:37 +00006374
Caroline Tice952b5382011-02-28 23:15:24 +00006375// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6376// zero-extends it to form a 32-bit word, and writes it to a register.
6377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006378EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006379{
6380#if 0
6381 if ConditionPassed() then
6382 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6383 base = Align(PC,4);
6384 address = if add then (base + imm32) else (base - imm32);
6385 data = MemU[address,2];
6386 if UnalignedSupport() || address<0> = ’0’ then
6387 R[t] = ZeroExtend(data, 32);
6388 else // Can only apply before ARMv7
6389 R[t] = bits(32) UNKNOWN;
6390#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006391
Caroline Tice952b5382011-02-28 23:15:24 +00006392 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006393
Greg Clayton7bc39082011-03-24 23:53:38 +00006394 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006395 {
6396 uint32_t t;
6397 uint32_t imm32;
6398 bool add;
6399
6400 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6401 switch (encoding)
6402 {
6403 case eEncodingT1:
6404 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6405 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6406 t = Bits32 (opcode, 15, 12);
6407 imm32 = Bits32 (opcode, 11, 0);
6408 add = BitIsSet (opcode, 23);
6409
6410 // if t == 13 then UNPREDICTABLE;
6411 if (t == 13)
6412 return false;
6413
6414 break;
6415
6416 case eEncodingA1:
6417 {
6418 uint32_t imm4H = Bits32 (opcode, 11, 8);
6419 uint32_t imm4L = Bits32 (opcode, 3, 0);
6420
6421 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6422 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006423 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006424 add = BitIsSet (opcode, 23);
6425
6426 // if t == 15 then UNPREDICTABLE;
6427 if (t == 15)
6428 return false;
6429 break;
6430 }
6431
6432 default:
6433 return false;
6434 }
6435
6436 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006437 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006438 if (!success)
6439 return false;
6440
6441 addr_t base = AlignPC (pc_value);
6442 addr_t address;
6443
6444 // address = if add then (base + imm32) else (base - imm32);
6445 if (add)
6446 address = base + imm32;
6447 else
6448 address = base - imm32;
6449
6450 // data = MemU[address,2];
6451 Register base_reg;
6452 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6453
6454 EmulateInstruction::Context context;
6455 context.type = eContextRegisterLoad;
6456 context.SetRegisterPlusOffset (base_reg, address - base);
6457
6458 uint64_t data = MemURead (context, address, 2, 0, &success);
6459 if (!success)
6460 return false;
6461
6462
6463 // if UnalignedSupport() || address<0> = ’0’ then
6464 if (UnalignedSupport () || BitIsClear (address, 0))
6465 {
6466 // R[t] = ZeroExtend(data, 32);
6467 context.type = eContextRegisterLoad;
6468 context.SetRegisterPlusOffset (base_reg, address - base);
6469 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6470 return false;
6471
6472 }
6473 else // Can only apply before ARMv7
6474 {
6475 // R[t] = bits(32) UNKNOWN;
6476 WriteBits32Unknown (t);
6477 }
6478 }
6479 return true;
6480}
6481
Caroline Tice0e6bc952011-03-01 18:00:42 +00006482// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6483// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6484// be shifted left by 0, 1, 2, or 3 bits.
6485bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006486EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006487{
6488#if 0
6489 if ConditionPassed() then
6490 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6491 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6492 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6493 address = if index then offset_addr else R[n];
6494 data = MemU[address,2];
6495 if wback then R[n] = offset_addr;
6496 if UnalignedSupport() || address<0> = ’0’ then
6497 R[t] = ZeroExtend(data, 32);
6498 else // Can only apply before ARMv7
6499 R[t] = bits(32) UNKNOWN;
6500#endif
6501
6502 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006503
Greg Clayton7bc39082011-03-24 23:53:38 +00006504 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006505 {
6506 uint32_t t;
6507 uint32_t n;
6508 uint32_t m;
6509 bool index;
6510 bool add;
6511 bool wback;
6512 ARM_ShifterType shift_t;
6513 uint32_t shift_n;
6514
6515 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6516 switch (encoding)
6517 {
6518 case eEncodingT1:
6519 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6520 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6521 t = Bits32 (opcode, 2, 0);
6522 n = Bits32 (opcode, 5, 3);
6523 m = Bits32 (opcode, 8, 6);
6524
6525 // index = TRUE; add = TRUE; wback = FALSE;
6526 index = true;
6527 add = true;
6528 wback = false;
6529
6530 // (shift_t, shift_n) = (SRType_LSL, 0);
6531 shift_t = SRType_LSL;
6532 shift_n = 0;
6533
6534 break;
6535
6536 case eEncodingT2:
6537 // if Rn == ’1111’ then SEE LDRH (literal);
6538 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6539 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6540 t = Bits32 (opcode, 15, 12);
6541 n = Bits32 (opcode, 19, 16);
6542 m = Bits32 (opcode, 3, 0);
6543
6544 // index = TRUE; add = TRUE; wback = FALSE;
6545 index = true;
6546 add = true;
6547 wback = false;
6548
6549 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6550 shift_t = SRType_LSL;
6551 shift_n = Bits32 (opcode, 5, 4);
6552
6553 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6554 if ((t == 13) || BadReg (m))
6555 return false;
6556 break;
6557
6558 case eEncodingA1:
6559 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6560 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6561 t = Bits32 (opcode, 15, 12);
6562 n = Bits32 (opcode, 19, 16);
6563 m = Bits32 (opcode, 3, 0);
6564
6565 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6566 index = BitIsSet (opcode, 24);
6567 add = BitIsSet (opcode, 23);
6568 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6569
6570 // (shift_t, shift_n) = (SRType_LSL, 0);
6571 shift_t = SRType_LSL;
6572 shift_n = 0;
6573
6574 // if t == 15 || m == 15 then UNPREDICTABLE;
6575 if ((t == 15) || (m == 15))
6576 return false;
6577
6578 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6579 if (wback && ((n == 15) || (n == t)))
6580 return false;
6581
6582 break;
6583
6584 default:
6585 return false;
6586 }
6587
6588 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6589
6590 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6591 if (!success)
6592 return false;
6593
6594 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6595
6596 addr_t offset_addr;
6597 addr_t address;
6598
6599 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6600 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6601 if (!success)
6602 return false;
6603
6604 if (add)
6605 offset_addr = Rn + offset;
6606 else
6607 offset_addr = Rn - offset;
6608
6609 // address = if index then offset_addr else R[n];
6610 if (index)
6611 address = offset_addr;
6612 else
6613 address = Rn;
6614
6615 // data = MemU[address,2];
6616 Register base_reg;
6617 Register offset_reg;
6618 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6619 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6620
6621 EmulateInstruction::Context context;
6622 context.type = eContextRegisterLoad;
6623 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6624 uint64_t data = MemURead (context, address, 2, 0, &success);
6625 if (!success)
6626 return false;
6627
6628 // if wback then R[n] = offset_addr;
6629 if (wback)
6630 {
6631 context.type = eContextAdjustBaseRegister;
6632 context.SetAddress (offset_addr);
6633 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6634 return false;
6635 }
6636
6637 // if UnalignedSupport() || address<0> = ’0’ then
6638 if (UnalignedSupport() || BitIsClear (address, 0))
6639 {
6640 // R[t] = ZeroExtend(data, 32);
6641 context.type = eContextRegisterLoad;
6642 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6643 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6644 return false;
6645 }
6646 else // Can only apply before ARMv7
6647 {
6648 // R[t] = bits(32) UNKNOWN;
6649 WriteBits32Unknown (t);
6650 }
6651 }
6652 return true;
6653}
6654
Caroline Ticea5e28af2011-03-01 21:53:03 +00006655// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6656// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6657// or pre-indexed addressing.
6658bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006659EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006660{
6661#if 0
6662 if ConditionPassed() then
6663 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6664 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6665 address = if index then offset_addr else R[n];
6666 R[t] = SignExtend(MemU[address,1], 32);
6667 if wback then R[n] = offset_addr;
6668#endif
6669
6670 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006671
Greg Clayton7bc39082011-03-24 23:53:38 +00006672 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006673 {
6674 uint32_t t;
6675 uint32_t n;
6676 uint32_t imm32;
6677 bool index;
6678 bool add;
6679 bool wback;
6680
6681 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6682 switch (encoding)
6683 {
6684 case eEncodingT1:
6685 // if Rt == ’1111’ then SEE PLI;
6686 // if Rn == ’1111’ then SEE LDRSB (literal);
6687 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6688 t = Bits32 (opcode, 15, 12);
6689 n = Bits32 (opcode, 19, 16);
6690 imm32 = Bits32 (opcode, 11, 0);
6691
6692 // index = TRUE; add = TRUE; wback = FALSE;
6693 index = true;
6694 add = true;
6695 wback = false;
6696
6697 // if t == 13 then UNPREDICTABLE;
6698 if (t == 13)
6699 return false;
6700
6701 break;
6702
6703 case eEncodingT2:
6704 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6705 // if Rn == ’1111’ then SEE LDRSB (literal);
6706 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6707 // if P == ’0’ && W == ’0’ then UNDEFINED;
6708 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6709 return false;
6710
6711 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6712 t = Bits32 (opcode, 15, 12);
6713 n = Bits32 (opcode, 19, 16);
6714 imm32 = Bits32 (opcode, 7, 0);
6715
6716 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6717 index = BitIsSet (opcode, 10);
6718 add = BitIsSet (opcode, 9);
6719 wback = BitIsSet (opcode, 8);
6720
6721 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6722 if (BadReg (t) || (wback && (n == t)))
6723 return false;
6724
6725 break;
6726
6727 case eEncodingA1:
6728 {
6729 // if Rn == ’1111’ then SEE LDRSB (literal);
6730 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6731 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6732 t = Bits32 (opcode, 15, 12);
6733 n = Bits32 (opcode, 19, 16);
6734
6735 uint32_t imm4H = Bits32 (opcode, 11, 8);
6736 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006737 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006738
6739 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6740 index = BitIsSet (opcode, 24);
6741 add = BitIsSet (opcode, 23);
6742 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6743
6744 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6745 if ((t == 15) || (wback && (n == t)))
6746 return false;
6747
6748 break;
6749 }
6750
6751 default:
6752 return false;
6753 }
6754
6755 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6756 if (!success)
6757 return false;
6758
6759 addr_t offset_addr;
6760 addr_t address;
6761
6762 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6763 if (add)
6764 offset_addr = Rn + imm32;
6765 else
6766 offset_addr = Rn - imm32;
6767
6768 // address = if index then offset_addr else R[n];
6769 if (index)
6770 address = offset_addr;
6771 else
6772 address = Rn;
6773
6774 // R[t] = SignExtend(MemU[address,1], 32);
6775 Register base_reg;
6776 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6777
6778 EmulateInstruction::Context context;
6779 context.type = eContextRegisterLoad;
6780 context.SetRegisterPlusOffset (base_reg, address - Rn);
6781
6782 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6783 if (!success)
6784 return false;
6785
6786 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6788 return false;
6789
6790 // if wback then R[n] = offset_addr;
6791 if (wback)
6792 {
6793 context.type = eContextAdjustBaseRegister;
6794 context.SetAddress (offset_addr);
6795 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6796 return false;
6797 }
6798 }
6799
6800 return true;
6801}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006802
Caroline Tice5f593912011-03-01 22:25:17 +00006803// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6804// sign-extends it to form a 32-bit word, and writes tit to a register.
6805bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006806EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006807{
6808#if 0
6809 if ConditionPassed() then
6810 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6811 base = Align(PC,4);
6812 address = if add then (base + imm32) else (base - imm32);
6813 R[t] = SignExtend(MemU[address,1], 32);
6814#endif
6815
6816 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006817
Greg Clayton7bc39082011-03-24 23:53:38 +00006818 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006819 {
6820 uint32_t t;
6821 uint32_t imm32;
6822 bool add;
6823
6824 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6825 switch (encoding)
6826 {
6827 case eEncodingT1:
6828 // if Rt == ’1111’ then SEE PLI;
6829 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6830 t = Bits32 (opcode, 15, 12);
6831 imm32 = Bits32 (opcode, 11, 0);
6832 add = BitIsSet (opcode, 23);
6833
6834 // if t == 13 then UNPREDICTABLE;
6835 if (t == 13)
6836 return false;
6837
6838 break;
6839
6840 case eEncodingA1:
6841 {
6842 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6843 t = Bits32 (opcode, 15, 12);
6844 uint32_t imm4H = Bits32 (opcode, 11, 8);
6845 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006846 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006847 add = BitIsSet (opcode, 23);
6848
6849 // if t == 15 then UNPREDICTABLE;
6850 if (t == 15)
6851 return false;
6852
6853 break;
6854 }
6855
6856 default:
6857 return false;
6858 }
6859
6860 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006861 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006862 if (!success)
6863 return false;
6864 uint64_t base = AlignPC (pc_value);
6865
6866 // address = if add then (base + imm32) else (base - imm32);
6867 addr_t address;
6868 if (add)
6869 address = base + imm32;
6870 else
6871 address = base - imm32;
6872
6873 // R[t] = SignExtend(MemU[address,1], 32);
6874 Register base_reg;
6875 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6876
6877 EmulateInstruction::Context context;
6878 context.type = eContextRegisterLoad;
6879 context.SetRegisterPlusOffset (base_reg, address - base);
6880
6881 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6882 if (!success)
6883 return false;
6884
6885 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6886 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6887 return false;
6888 }
6889 return true;
6890}
6891
Caroline Tice672f3112011-03-01 23:55:59 +00006892// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6893// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6894// shifted left by 0, 1, 2, or 3 bits.
6895bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006896EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00006897{
6898#if 0
6899 if ConditionPassed() then
6900 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6901 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6902 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6903 address = if index then offset_addr else R[n];
6904 R[t] = SignExtend(MemU[address,1], 32);
6905 if wback then R[n] = offset_addr;
6906#endif
6907
6908 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00006909
Greg Clayton7bc39082011-03-24 23:53:38 +00006910 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00006911 {
6912 uint32_t t;
6913 uint32_t n;
6914 uint32_t m;
6915 bool index;
6916 bool add;
6917 bool wback;
6918 ARM_ShifterType shift_t;
6919 uint32_t shift_n;
6920
6921 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6922 switch (encoding)
6923 {
6924 case eEncodingT1:
6925 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6926 t = Bits32 (opcode, 2, 0);
6927 n = Bits32 (opcode, 5, 3);
6928 m = Bits32 (opcode, 8, 6);
6929
6930 // index = TRUE; add = TRUE; wback = FALSE;
6931 index = true;
6932 add = true;
6933 wback = false;
6934
6935 // (shift_t, shift_n) = (SRType_LSL, 0);
6936 shift_t = SRType_LSL;
6937 shift_n = 0;
6938
6939 break;
6940
6941 case eEncodingT2:
6942 // if Rt == ’1111’ then SEE PLI;
6943 // if Rn == ’1111’ then SEE LDRSB (literal);
6944 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6945 t = Bits32 (opcode, 15, 12);
6946 n = Bits32 (opcode, 19, 16);
6947 m = Bits32 (opcode, 3, 0);
6948
6949 // index = TRUE; add = TRUE; wback = FALSE;
6950 index = true;
6951 add = true;
6952 wback = false;
6953
6954 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6955 shift_t = SRType_LSL;
6956 shift_n = Bits32 (opcode, 5, 4);
6957
6958 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6959 if ((t == 13) || BadReg (m))
6960 return false;
6961 break;
6962
6963 case eEncodingA1:
6964 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6965 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6966 t = Bits32 (opcode, 15, 12);
6967 n = Bits32 (opcode, 19, 16);
6968 m = Bits32 (opcode, 3, 0);
6969
6970 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6971 index = BitIsSet (opcode, 24);
6972 add = BitIsSet (opcode, 23);
6973 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6974
6975 // (shift_t, shift_n) = (SRType_LSL, 0);
6976 shift_t = SRType_LSL;
6977 shift_n = 0;
6978
6979 // if t == 15 || m == 15 then UNPREDICTABLE;
6980 if ((t == 15) || (m == 15))
6981 return false;
6982
6983 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6984 if (wback && ((n == 15) || (n == t)))
6985 return false;
6986 break;
6987
6988 default:
6989 return false;
6990 }
6991
6992 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6993 if (!success)
6994 return false;
6995
6996 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6997 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6998
6999 addr_t offset_addr;
7000 addr_t address;
7001
7002 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7003 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7004 if (!success)
7005 return false;
7006
7007 if (add)
7008 offset_addr = Rn + offset;
7009 else
7010 offset_addr = Rn - offset;
7011
7012 // address = if index then offset_addr else R[n];
7013 if (index)
7014 address = offset_addr;
7015 else
7016 address = Rn;
7017
7018 // R[t] = SignExtend(MemU[address,1], 32);
7019 Register base_reg;
7020 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7021 Register offset_reg;
7022 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7023
7024 EmulateInstruction::Context context;
7025 context.type = eContextRegisterLoad;
7026 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7027
7028 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7029 if (!success)
7030 return false;
7031
7032 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7033 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7034 return false;
7035
7036 // if wback then R[n] = offset_addr;
7037 if (wback)
7038 {
7039 context.type = eContextAdjustBaseRegister;
7040 context.SetAddress (offset_addr);
7041 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7042 return false;
7043 }
7044 }
7045 return true;
7046}
7047
Caroline Tice78fb5632011-03-02 00:39:42 +00007048// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7049// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7050// pre-indexed addressing.
7051bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007052EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007053{
7054#if 0
7055 if ConditionPassed() then
7056 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7057 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7058 address = if index then offset_addr else R[n];
7059 data = MemU[address,2];
7060 if wback then R[n] = offset_addr;
7061 if UnalignedSupport() || address<0> = ’0’ then
7062 R[t] = SignExtend(data, 32);
7063 else // Can only apply before ARMv7
7064 R[t] = bits(32) UNKNOWN;
7065#endif
7066
7067 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007068
Greg Clayton7bc39082011-03-24 23:53:38 +00007069 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007070 {
7071 uint32_t t;
7072 uint32_t n;
7073 uint32_t imm32;
7074 bool index;
7075 bool add;
7076 bool wback;
7077
7078 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7079 switch (encoding)
7080 {
7081 case eEncodingT1:
7082 // if Rn == ’1111’ then SEE LDRSH (literal);
7083 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7084 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7085 t = Bits32 (opcode, 15, 12);
7086 n = Bits32 (opcode, 19, 16);
7087 imm32 = Bits32 (opcode, 11, 0);
7088
7089 // index = TRUE; add = TRUE; wback = FALSE;
7090 index = true;
7091 add = true;
7092 wback = false;
7093
7094 // if t == 13 then UNPREDICTABLE;
7095 if (t == 13)
7096 return false;
7097
7098 break;
7099
7100 case eEncodingT2:
7101 // if Rn == ’1111’ then SEE LDRSH (literal);
7102 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7103 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7104 // if P == ’0’ && W == ’0’ then UNDEFINED;
7105 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7106 return false;
7107
7108 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7109 t = Bits32 (opcode, 15, 12);
7110 n = Bits32 (opcode, 19, 16);
7111 imm32 = Bits32 (opcode, 7, 0);
7112
7113 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7114 index = BitIsSet (opcode, 10);
7115 add = BitIsSet (opcode, 9);
7116 wback = BitIsSet (opcode, 8);
7117
7118 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7119 if (BadReg (t) || (wback && (n == t)))
7120 return false;
7121
7122 break;
7123
7124 case eEncodingA1:
7125 {
7126 // if Rn == ’1111’ then SEE LDRSH (literal);
7127 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7128 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7129 t = Bits32 (opcode, 15, 12);
7130 n = Bits32 (opcode, 19, 16);
7131 uint32_t imm4H = Bits32 (opcode, 11,8);
7132 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007133 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007134
7135 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7136 index = BitIsSet (opcode, 24);
7137 add = BitIsSet (opcode, 23);
7138 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7139
7140 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7141 if ((t == 15) || (wback && (n == t)))
7142 return false;
7143
7144 break;
7145 }
7146
7147 default:
7148 return false;
7149 }
7150
7151 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7152 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7153 if (!success)
7154 return false;
7155
7156 addr_t offset_addr;
7157 if (add)
7158 offset_addr = Rn + imm32;
7159 else
7160 offset_addr = Rn - imm32;
7161
7162 // address = if index then offset_addr else R[n];
7163 addr_t address;
7164 if (index)
7165 address = offset_addr;
7166 else
7167 address = Rn;
7168
7169 // data = MemU[address,2];
7170 Register base_reg;
7171 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7172
7173 EmulateInstruction::Context context;
7174 context.type = eContextRegisterLoad;
7175 context.SetRegisterPlusOffset (base_reg, address - Rn);
7176
7177 uint64_t data = MemURead (context, address, 2, 0, &success);
7178 if (!success)
7179 return false;
7180
7181 // if wback then R[n] = offset_addr;
7182 if (wback)
7183 {
7184 context.type = eContextAdjustBaseRegister;
7185 context.SetAddress (offset_addr);
7186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7187 return false;
7188 }
7189
7190 // if UnalignedSupport() || address<0> = ’0’ then
7191 if (UnalignedSupport() || BitIsClear (address, 0))
7192 {
7193 // R[t] = SignExtend(data, 32);
7194 int64_t signed_data = llvm::SignExtend64<16>(data);
7195 context.type = eContextRegisterLoad;
7196 context.SetRegisterPlusOffset (base_reg, address - Rn);
7197 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7198 return false;
7199 }
7200 else // Can only apply before ARMv7
7201 {
7202 // R[t] = bits(32) UNKNOWN;
7203 WriteBits32Unknown (t);
7204 }
7205 }
7206 return true;
7207}
7208
Caroline Ticed2fac092011-03-02 19:45:34 +00007209// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7210// sign-extends it to from a 32-bit word, and writes it to a register.
7211bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007212EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007213{
7214#if 0
7215 if ConditionPassed() then
7216 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7217 base = Align(PC,4);
7218 address = if add then (base + imm32) else (base - imm32);
7219 data = MemU[address,2];
7220 if UnalignedSupport() || address<0> = ’0’ then
7221 R[t] = SignExtend(data, 32);
7222 else // Can only apply before ARMv7
7223 R[t] = bits(32) UNKNOWN;
7224#endif
7225
7226 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007227
Greg Clayton7bc39082011-03-24 23:53:38 +00007228 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007229 {
7230 uint32_t t;
7231 uint32_t imm32;
7232 bool add;
7233
7234 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7235 switch (encoding)
7236 {
7237 case eEncodingT1:
7238 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7239 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7240 t = Bits32 (opcode, 15, 12);
7241 imm32 = Bits32 (opcode, 11, 0);
7242 add = BitIsSet (opcode, 23);
7243
7244 // if t == 13 then UNPREDICTABLE;
7245 if (t == 13)
7246 return false;
7247
7248 break;
7249
7250 case eEncodingA1:
7251 {
7252 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7253 t = Bits32 (opcode, 15, 12);
7254 uint32_t imm4H = Bits32 (opcode, 11, 8);
7255 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007256 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007257 add = BitIsSet (opcode, 23);
7258
7259 // if t == 15 then UNPREDICTABLE;
7260 if (t == 15)
7261 return false;
7262
7263 break;
7264 }
7265 default:
7266 return false;
7267 }
7268
7269 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007270 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007271 if (!success)
7272 return false;
7273
7274 uint64_t base = AlignPC (pc_value);
7275
7276 addr_t address;
7277 // address = if add then (base + imm32) else (base - imm32);
7278 if (add)
7279 address = base + imm32;
7280 else
7281 address = base - imm32;
7282
7283 // data = MemU[address,2];
7284 Register base_reg;
7285 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7286
7287 EmulateInstruction::Context context;
7288 context.type = eContextRegisterLoad;
7289 context.SetRegisterPlusOffset (base_reg, imm32);
7290
7291 uint64_t data = MemURead (context, address, 2, 0, &success);
7292 if (!success)
7293 return false;
7294
7295 // if UnalignedSupport() || address<0> = ’0’ then
7296 if (UnalignedSupport() || BitIsClear (address, 0))
7297 {
7298 // R[t] = SignExtend(data, 32);
7299 int64_t signed_data = llvm::SignExtend64<16>(data);
7300 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7301 return false;
7302 }
7303 else // Can only apply before ARMv7
7304 {
7305 // R[t] = bits(32) UNKNOWN;
7306 WriteBits32Unknown (t);
7307 }
7308 }
7309 return true;
7310}
7311
Caroline Tice291a3e92011-03-02 21:13:44 +00007312// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7313// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7314// shifted left by 0, 1, 2, or 3 bits.
7315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007316EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007317{
7318#if 0
7319 if ConditionPassed() then
7320 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7321 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7322 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7323 address = if index then offset_addr else R[n];
7324 data = MemU[address,2];
7325 if wback then R[n] = offset_addr;
7326 if UnalignedSupport() || address<0> = ’0’ then
7327 R[t] = SignExtend(data, 32);
7328 else // Can only apply before ARMv7
7329 R[t] = bits(32) UNKNOWN;
7330#endif
7331
7332 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007333
Greg Clayton7bc39082011-03-24 23:53:38 +00007334 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007335 {
7336 uint32_t t;
7337 uint32_t n;
7338 uint32_t m;
7339 bool index;
7340 bool add;
7341 bool wback;
7342 ARM_ShifterType shift_t;
7343 uint32_t shift_n;
7344
7345 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7346 switch (encoding)
7347 {
7348 case eEncodingT1:
7349 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7350 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7351 t = Bits32 (opcode, 2, 0);
7352 n = Bits32 (opcode, 5, 3);
7353 m = Bits32 (opcode, 8, 6);
7354
7355 // index = TRUE; add = TRUE; wback = FALSE;
7356 index = true;
7357 add = true;
7358 wback = false;
7359
7360 // (shift_t, shift_n) = (SRType_LSL, 0);
7361 shift_t = SRType_LSL;
7362 shift_n = 0;
7363
7364 break;
7365
7366 case eEncodingT2:
7367 // if Rn == ’1111’ then SEE LDRSH (literal);
7368 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7369 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7370 t = Bits32 (opcode, 15, 12);
7371 n = Bits32 (opcode, 19, 16);
7372 m = Bits32 (opcode, 3, 0);
7373
7374 // index = TRUE; add = TRUE; wback = FALSE;
7375 index = true;
7376 add = true;
7377 wback = false;
7378
7379 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7380 shift_t = SRType_LSL;
7381 shift_n = Bits32 (opcode, 5, 4);
7382
7383 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7384 if ((t == 13) || BadReg (m))
7385 return false;
7386
7387 break;
7388
7389 case eEncodingA1:
7390 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7391 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7392 t = Bits32 (opcode, 15, 12);
7393 n = Bits32 (opcode, 19, 16);
7394 m = Bits32 (opcode, 3, 0);
7395
7396 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7397 index = BitIsSet (opcode, 24);
7398 add = BitIsSet (opcode, 23);
7399 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7400
7401 // (shift_t, shift_n) = (SRType_LSL, 0);
7402 shift_t = SRType_LSL;
7403 shift_n = 0;
7404
7405 // if t == 15 || m == 15 then UNPREDICTABLE;
7406 if ((t == 15) || (m == 15))
7407 return false;
7408
7409 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7410 if (wback && ((n == 15) || (n == t)))
7411 return false;
7412
7413 break;
7414
7415 default:
7416 break;
7417 }
7418
7419 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7420 if (!success)
7421 return false;
7422
7423 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7424 if (!success)
7425 return false;
7426
7427 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7428 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7429
7430 addr_t offset_addr;
7431 addr_t address;
7432
7433 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7434 if (add)
7435 offset_addr = Rn + offset;
7436 else
7437 offset_addr = Rn - offset;
7438
7439 // address = if index then offset_addr else R[n];
7440 if (index)
7441 address = offset_addr;
7442 else
7443 address = Rn;
7444
7445 // data = MemU[address,2];
7446 Register base_reg;
7447 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7448
7449 Register offset_reg;
7450 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7451
7452 EmulateInstruction::Context context;
7453 context.type = eContextRegisterLoad;
7454 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7455
7456 uint64_t data = MemURead (context, address, 2, 0, &success);
7457 if (!success)
7458 return false;
7459
7460 // if wback then R[n] = offset_addr;
7461 if (wback)
7462 {
7463 context.type = eContextAdjustBaseRegister;
7464 context.SetAddress (offset_addr);
7465 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7466 return false;
7467 }
7468
7469 // if UnalignedSupport() || address<0> = ’0’ then
7470 if (UnalignedSupport() || BitIsClear (address, 0))
7471 {
7472 // R[t] = SignExtend(data, 32);
7473 context.type = eContextRegisterLoad;
7474 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7475
7476 int64_t signed_data = llvm::SignExtend64<16>(data);
7477 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7478 return false;
7479 }
7480 else // Can only apply before ARMv7
7481 {
7482 // R[t] = bits(32) UNKNOWN;
7483 WriteBits32Unknown (t);
7484 }
7485 }
7486 return true;
7487}
Caroline Tice6bf65162011-03-03 17:42:58 +00007488
7489// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7490// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7491bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007492EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007493{
7494#if 0
7495 if ConditionPassed() then
7496 EncodingSpecificOperations();
7497 rotated = ROR(R[m], rotation);
7498 R[d] = SignExtend(rotated<7:0>, 32);
7499#endif
7500
7501 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007502
Greg Clayton7bc39082011-03-24 23:53:38 +00007503 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007504 {
7505 uint32_t d;
7506 uint32_t m;
7507 uint32_t rotation;
7508
7509 // EncodingSpecificOperations();
7510 switch (encoding)
7511 {
7512 case eEncodingT1:
7513 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7514 d = Bits32 (opcode, 2, 0);
7515 m = Bits32 (opcode, 5, 3);
7516 rotation = 0;
7517
7518 break;
7519
7520 case eEncodingT2:
7521 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7522 d = Bits32 (opcode, 11, 8);
7523 m = Bits32 (opcode, 3, 0);
7524 rotation = Bits32 (opcode, 5, 4) << 3;
7525
7526 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7527 if (BadReg (d) || BadReg (m))
7528 return false;
7529
7530 break;
7531
7532 case eEncodingA1:
7533 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7534 d = Bits32 (opcode, 15, 12);
7535 m = Bits32 (opcode, 3, 0);
7536 rotation = Bits32 (opcode, 11, 10) << 3;
7537
7538 // if d == 15 || m == 15 then UNPREDICTABLE;
7539 if ((d == 15) || (m == 15))
7540 return false;
7541
7542 break;
7543
7544 default:
7545 return false;
7546 }
7547
Caroline Tice868198b2011-03-03 18:04:49 +00007548 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7549 if (!success)
7550 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007551
7552 // rotated = ROR(R[m], rotation);
7553 uint64_t rotated = ROR (Rm, rotation);
7554
7555 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007556 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007557
7558 Register source_reg;
7559 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7560
7561 EmulateInstruction::Context context;
7562 context.type = eContextRegisterLoad;
7563 context.SetRegister (source_reg);
7564
Caroline Tice8ce96d92011-03-03 18:27:17 +00007565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007566 return false;
7567 }
7568 return true;
7569}
Caroline Tice291a3e92011-03-02 21:13:44 +00007570
Caroline Tice868198b2011-03-03 18:04:49 +00007571// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7572// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7573bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007574EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007575{
7576#if 0
7577 if ConditionPassed() then
7578 EncodingSpecificOperations();
7579 rotated = ROR(R[m], rotation);
7580 R[d] = SignExtend(rotated<15:0>, 32);
7581#endif
7582
7583 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007584
Greg Clayton7bc39082011-03-24 23:53:38 +00007585 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007586 {
7587 uint32_t d;
7588 uint32_t m;
7589 uint32_t rotation;
7590
7591 // EncodingSpecificOperations();
7592 switch (encoding)
7593 {
7594 case eEncodingT1:
7595 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7596 d = Bits32 (opcode, 2, 0);
7597 m = Bits32 (opcode, 5, 3);
7598 rotation = 0;
7599
7600 break;
7601
7602 case eEncodingT2:
7603 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7604 d = Bits32 (opcode, 11, 8);
7605 m = Bits32 (opcode, 3, 0);
7606 rotation = Bits32 (opcode, 5, 4) << 3;
7607
7608 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7609 if (BadReg (d) || BadReg (m))
7610 return false;
7611
7612 break;
7613
7614 case eEncodingA1:
7615 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7616 d = Bits32 (opcode, 15, 12);
7617 m = Bits32 (opcode, 3, 0);
7618 rotation = Bits32 (opcode, 11, 10) << 3;
7619
7620 // if d == 15 || m == 15 then UNPREDICTABLE;
7621 if ((d == 15) || (m == 15))
7622 return false;
7623
7624 break;
7625
7626 default:
7627 return false;
7628 }
7629
7630 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7631 if (!success)
7632 return false;
7633
7634 // rotated = ROR(R[m], rotation);
7635 uint64_t rotated = ROR (Rm, rotation);
7636
7637 // R[d] = SignExtend(rotated<15:0>, 32);
7638 Register source_reg;
7639 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7640
7641 EmulateInstruction::Context context;
7642 context.type = eContextRegisterLoad;
7643 context.SetRegister (source_reg);
7644
Caroline Tice8ce96d92011-03-03 18:27:17 +00007645 int64_t data = llvm::SignExtend64<16> (rotated);
7646 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007647 return false;
7648 }
7649
7650 return true;
7651}
7652
Caroline Tice8ce96d92011-03-03 18:27:17 +00007653// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7654// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7655bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007656EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007657{
7658#if 0
7659 if ConditionPassed() then
7660 EncodingSpecificOperations();
7661 rotated = ROR(R[m], rotation);
7662 R[d] = ZeroExtend(rotated<7:0>, 32);
7663#endif
7664
7665 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007666
Greg Clayton7bc39082011-03-24 23:53:38 +00007667 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007668 {
7669 uint32_t d;
7670 uint32_t m;
7671 uint32_t rotation;
7672
7673 // EncodingSpecificOperations();
7674 switch (encoding)
7675 {
7676 case eEncodingT1:
7677 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7678 d = Bits32 (opcode, 2, 0);
7679 m = Bits32 (opcode, 5, 3);
7680 rotation = 0;
7681
7682 break;
7683
7684 case eEncodingT2:
7685 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7686 d = Bits32 (opcode, 11, 8);
7687 m = Bits32 (opcode, 3, 0);
7688 rotation = Bits32 (opcode, 5, 4) << 3;
7689
7690 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7691 if (BadReg (d) || BadReg (m))
7692 return false;
7693
7694 break;
7695
7696 case eEncodingA1:
7697 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7698 d = Bits32 (opcode, 15, 12);
7699 m = Bits32 (opcode, 3, 0);
7700 rotation = Bits32 (opcode, 11, 10) << 3;
7701
7702 // if d == 15 || m == 15 then UNPREDICTABLE;
7703 if ((d == 15) || (m == 15))
7704 return false;
7705
7706 break;
7707
7708 default:
7709 return false;
7710 }
7711
7712 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7713 if (!success)
7714 return false;
7715
7716 // rotated = ROR(R[m], rotation);
7717 uint64_t rotated = ROR (Rm, rotation);
7718
7719 // R[d] = ZeroExtend(rotated<7:0>, 32);
7720 Register source_reg;
7721 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7722
7723 EmulateInstruction::Context context;
7724 context.type = eContextRegisterLoad;
7725 context.SetRegister (source_reg);
7726
7727 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7728 return false;
7729 }
7730 return true;
7731}
7732
Caroline Tice11555f22011-03-03 18:48:58 +00007733// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7734// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7735bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007736EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007737{
7738#if 0
7739 if ConditionPassed() then
7740 EncodingSpecificOperations();
7741 rotated = ROR(R[m], rotation);
7742 R[d] = ZeroExtend(rotated<15:0>, 32);
7743#endif
7744
7745 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007746
Greg Clayton7bc39082011-03-24 23:53:38 +00007747 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007748 {
7749 uint32_t d;
7750 uint32_t m;
7751 uint32_t rotation;
7752
7753 switch (encoding)
7754 {
7755 case eEncodingT1:
7756 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7757 d = Bits32 (opcode, 2, 0);
7758 m = Bits32 (opcode, 5, 3);
7759 rotation = 0;
7760
7761 break;
7762
7763 case eEncodingT2:
7764 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7765 d = Bits32 (opcode, 11, 8);
7766 m = Bits32 (opcode, 3, 0);
7767 rotation = Bits32 (opcode, 5, 4) << 3;
7768
7769 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7770 if (BadReg (d) || BadReg (m))
7771 return false;
7772
7773 break;
7774
7775 case eEncodingA1:
7776 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7777 d = Bits32 (opcode, 15, 12);
7778 m = Bits32 (opcode, 3, 0);
7779 rotation = Bits32 (opcode, 11, 10) << 3;
7780
7781 // if d == 15 || m == 15 then UNPREDICTABLE;
7782 if ((d == 15) || (m == 15))
7783 return false;
7784
7785 break;
7786
7787 default:
7788 return false;
7789 }
7790
7791 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7792 if (!success)
7793 return false;
7794
7795 // rotated = ROR(R[m], rotation);
7796 uint64_t rotated = ROR (Rm, rotation);
7797
7798 // R[d] = ZeroExtend(rotated<15:0>, 32);
7799 Register source_reg;
7800 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7801
7802 EmulateInstruction::Context context;
7803 context.type = eContextRegisterLoad;
7804 context.SetRegister (source_reg);
7805
7806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7807 return false;
7808 }
7809 return true;
7810}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007811
7812// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7813// word respectively.
7814bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007815EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007816{
7817#if 0
7818 if ConditionPassed() then
7819 EncodingSpecificOperations();
7820 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7821 UNPREDICTABLE;
7822 else
7823 address = if increment then R[n] else R[n]-8;
7824 if wordhigher then address = address+4;
7825 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7826 BranchWritePC(MemA[address,4]);
7827 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7828#endif
7829
7830 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007831
Greg Clayton7bc39082011-03-24 23:53:38 +00007832 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007833 {
7834 uint32_t n;
7835 bool wback;
7836 bool increment;
7837 bool wordhigher;
7838
7839 // EncodingSpecificOperations();
7840 switch (encoding)
7841 {
7842 case eEncodingT1:
7843 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
7844 n = Bits32 (opcode, 19, 16);
7845 wback = BitIsSet (opcode, 21);
7846 increment = false;
7847 wordhigher = false;
7848
7849 // if n == 15 then UNPREDICTABLE;
7850 if (n == 15)
7851 return false;
7852
7853 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7854 if (InITBlock() && !LastInITBlock())
7855 return false;
7856
7857 break;
7858
7859 case eEncodingT2:
7860 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
7861 n = Bits32 (opcode, 19, 16);
7862 wback = BitIsSet (opcode, 21);
7863 increment = true;
7864 wordhigher = false;
7865
7866 // if n == 15 then UNPREDICTABLE;
7867 if (n == 15)
7868 return false;
7869
7870 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7871 if (InITBlock() && !LastInITBlock())
7872 return false;
7873
7874 break;
7875
7876 case eEncodingA1:
7877 // n = UInt(Rn);
7878 n = Bits32 (opcode, 19, 16);
7879
7880 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
7881 wback = BitIsSet (opcode, 21);
7882 increment = BitIsSet (opcode, 23);
7883 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7884
7885 // if n == 15 then UNPREDICTABLE;
7886 if (n == 15)
7887 return false;
7888
7889 break;
7890
7891 default:
7892 return false;
7893 }
7894
7895 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7896 if (!CurrentModeIsPrivileged ())
7897 // UNPREDICTABLE;
7898 return false;
7899 else
7900 {
7901 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7902 if (!success)
7903 return false;
7904
7905 addr_t address;
7906 // address = if increment then R[n] else R[n]-8;
7907 if (increment)
7908 address = Rn;
7909 else
7910 address = Rn - 8;
7911
7912 // if wordhigher then address = address+4;
7913 if (wordhigher)
7914 address = address + 4;
7915
7916 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7917 Register base_reg;
7918 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7919
7920 EmulateInstruction::Context context;
7921 context.type = eContextReturnFromException;
7922 context.SetRegisterPlusOffset (base_reg, address - Rn);
7923
7924 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7925 if (!success)
7926 return false;
7927
7928 CPSRWriteByInstr (data, 15, true);
7929
7930 // BranchWritePC(MemA[address,4]);
7931 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7932 if (!success)
7933 return false;
7934
7935 BranchWritePC (context, data2);
7936
7937 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7938 if (wback)
7939 {
7940 context.type = eContextAdjustBaseRegister;
7941 if (increment)
7942 {
7943 context.SetOffset (8);
7944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7945 return false;
7946 }
7947 else
7948 {
7949 context.SetOffset (-8);
7950 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
7951 return false;
7952 }
7953 } // if wback
7954 }
7955 } // if ConditionPassed()
7956 return true;
7957}
Caroline Tice11555f22011-03-03 18:48:58 +00007958
Johnny Chen2115b412011-02-21 23:42:44 +00007959// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7960// and writes the result to the destination register. It can optionally update the condition flags based on
7961// the result.
7962bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007963EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00007964{
7965#if 0
7966 // ARM pseudo code...
7967 if ConditionPassed() then
7968 EncodingSpecificOperations();
7969 result = R[n] EOR imm32;
7970 if d == 15 then // Can only occur for ARM encoding
7971 ALUWritePC(result); // setflags is always FALSE here
7972 else
7973 R[d] = result;
7974 if setflags then
7975 APSR.N = result<31>;
7976 APSR.Z = IsZeroBit(result);
7977 APSR.C = carry;
7978 // APSR.V unchanged
7979#endif
7980
7981 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00007982
Greg Clayton7bc39082011-03-24 23:53:38 +00007983 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00007984 {
7985 uint32_t Rd, Rn;
7986 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7987 bool setflags;
7988 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7989 switch (encoding)
7990 {
7991 case eEncodingT1:
7992 Rd = Bits32(opcode, 11, 8);
7993 Rn = Bits32(opcode, 19, 16);
7994 setflags = BitIsSet(opcode, 20);
7995 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7996 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7997 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00007998 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00007999 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8000 return false;
8001 break;
8002 case eEncodingA1:
8003 Rd = Bits32(opcode, 15, 12);
8004 Rn = Bits32(opcode, 19, 16);
8005 setflags = BitIsSet(opcode, 20);
8006 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8007 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8008 // TODO: Emulate SUBS PC, LR and related instructions.
8009 if (Rd == 15 && setflags)
8010 return false;
8011 break;
8012 default:
8013 return false;
8014 }
8015
8016 // Read the first operand.
8017 uint32_t val1 = ReadCoreReg(Rn, &success);
8018 if (!success)
8019 return false;
8020
8021 uint32_t result = val1 ^ imm32;
8022
8023 EmulateInstruction::Context context;
8024 context.type = EmulateInstruction::eContextImmediate;
8025 context.SetNoArgs ();
8026
8027 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8028 return false;
8029 }
8030 return true;
8031}
8032
8033// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8034// optionally-shifted register value, and writes the result to the destination register.
8035// It can optionally update the condition flags based on the result.
8036bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008037EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008038{
8039#if 0
8040 // ARM pseudo code...
8041 if ConditionPassed() then
8042 EncodingSpecificOperations();
8043 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8044 result = R[n] EOR shifted;
8045 if d == 15 then // Can only occur for ARM encoding
8046 ALUWritePC(result); // setflags is always FALSE here
8047 else
8048 R[d] = result;
8049 if setflags then
8050 APSR.N = result<31>;
8051 APSR.Z = IsZeroBit(result);
8052 APSR.C = carry;
8053 // APSR.V unchanged
8054#endif
8055
8056 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008057
Greg Clayton7bc39082011-03-24 23:53:38 +00008058 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008059 {
8060 uint32_t Rd, Rn, Rm;
8061 ARM_ShifterType shift_t;
8062 uint32_t shift_n; // the shift applied to the value read from Rm
8063 bool setflags;
8064 uint32_t carry;
8065 switch (encoding)
8066 {
8067 case eEncodingT1:
8068 Rd = Rn = Bits32(opcode, 2, 0);
8069 Rm = Bits32(opcode, 5, 3);
8070 setflags = !InITBlock();
8071 shift_t = SRType_LSL;
8072 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008073 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008074 case eEncodingT2:
8075 Rd = Bits32(opcode, 11, 8);
8076 Rn = Bits32(opcode, 19, 16);
8077 Rm = Bits32(opcode, 3, 0);
8078 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008079 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8080 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008081 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008082 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008083 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8084 return false;
8085 break;
8086 case eEncodingA1:
8087 Rd = Bits32(opcode, 15, 12);
8088 Rn = Bits32(opcode, 19, 16);
8089 Rm = Bits32(opcode, 3, 0);
8090 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008091 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008092 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8093 // TODO: Emulate SUBS PC, LR and related instructions.
8094 if (Rd == 15 && setflags)
8095 return false;
8096 break;
8097 default:
8098 return false;
8099 }
8100
8101 // Read the first operand.
8102 uint32_t val1 = ReadCoreReg(Rn, &success);
8103 if (!success)
8104 return false;
8105
8106 // Read the second operand.
8107 uint32_t val2 = ReadCoreReg(Rm, &success);
8108 if (!success)
8109 return false;
8110
8111 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8112 uint32_t result = val1 ^ shifted;
8113
8114 EmulateInstruction::Context context;
8115 context.type = EmulateInstruction::eContextImmediate;
8116 context.SetNoArgs ();
8117
8118 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8119 return false;
8120 }
8121 return true;
8122}
8123
Johnny Chen7c5234d2011-02-18 23:41:11 +00008124// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8125// writes the result to the destination register. It can optionally update the condition flags based
8126// on the result.
8127bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008128EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008129{
8130#if 0
8131 // ARM pseudo code...
8132 if ConditionPassed() then
8133 EncodingSpecificOperations();
8134 result = R[n] OR imm32;
8135 if d == 15 then // Can only occur for ARM encoding
8136 ALUWritePC(result); // setflags is always FALSE here
8137 else
8138 R[d] = result;
8139 if setflags then
8140 APSR.N = result<31>;
8141 APSR.Z = IsZeroBit(result);
8142 APSR.C = carry;
8143 // APSR.V unchanged
8144#endif
8145
8146 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008147
Greg Clayton7bc39082011-03-24 23:53:38 +00008148 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008149 {
8150 uint32_t Rd, Rn;
8151 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8152 bool setflags;
8153 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8154 switch (encoding)
8155 {
8156 case eEncodingT1:
8157 Rd = Bits32(opcode, 11, 8);
8158 Rn = Bits32(opcode, 19, 16);
8159 setflags = BitIsSet(opcode, 20);
8160 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8161 // if Rn == ‘1111’ then SEE MOV (immediate);
8162 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008163 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008164 if (BadReg(Rd) || Rn == 13)
8165 return false;
8166 break;
8167 case eEncodingA1:
8168 Rd = Bits32(opcode, 15, 12);
8169 Rn = Bits32(opcode, 19, 16);
8170 setflags = BitIsSet(opcode, 20);
8171 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8172 // TODO: Emulate SUBS PC, LR and related instructions.
8173 if (Rd == 15 && setflags)
8174 return false;
8175 break;
8176 default:
8177 return false;
8178 }
8179
8180 // Read the first operand.
8181 uint32_t val1 = ReadCoreReg(Rn, &success);
8182 if (!success)
8183 return false;
8184
8185 uint32_t result = val1 | imm32;
8186
8187 EmulateInstruction::Context context;
8188 context.type = EmulateInstruction::eContextImmediate;
8189 context.SetNoArgs ();
8190
8191 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8192 return false;
8193 }
8194 return true;
8195}
8196
8197// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8198// value, and writes the result to the destination register. It can optionally update the condition flags based
8199// on the result.
8200bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008201EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008202{
8203#if 0
8204 // ARM pseudo code...
8205 if ConditionPassed() then
8206 EncodingSpecificOperations();
8207 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8208 result = R[n] OR shifted;
8209 if d == 15 then // Can only occur for ARM encoding
8210 ALUWritePC(result); // setflags is always FALSE here
8211 else
8212 R[d] = result;
8213 if setflags then
8214 APSR.N = result<31>;
8215 APSR.Z = IsZeroBit(result);
8216 APSR.C = carry;
8217 // APSR.V unchanged
8218#endif
8219
8220 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008221
Greg Clayton7bc39082011-03-24 23:53:38 +00008222 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008223 {
8224 uint32_t Rd, Rn, Rm;
8225 ARM_ShifterType shift_t;
8226 uint32_t shift_n; // the shift applied to the value read from Rm
8227 bool setflags;
8228 uint32_t carry;
8229 switch (encoding)
8230 {
8231 case eEncodingT1:
8232 Rd = Rn = Bits32(opcode, 2, 0);
8233 Rm = Bits32(opcode, 5, 3);
8234 setflags = !InITBlock();
8235 shift_t = SRType_LSL;
8236 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008237 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008238 case eEncodingT2:
8239 Rd = Bits32(opcode, 11, 8);
8240 Rn = Bits32(opcode, 19, 16);
8241 Rm = Bits32(opcode, 3, 0);
8242 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008243 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8244 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008245 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008246 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008247 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8248 return false;
8249 break;
8250 case eEncodingA1:
8251 Rd = Bits32(opcode, 15, 12);
8252 Rn = Bits32(opcode, 19, 16);
8253 Rm = Bits32(opcode, 3, 0);
8254 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008255 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008256 // TODO: Emulate SUBS PC, LR and related instructions.
8257 if (Rd == 15 && setflags)
8258 return false;
8259 break;
8260 default:
8261 return false;
8262 }
8263
8264 // Read the first operand.
8265 uint32_t val1 = ReadCoreReg(Rn, &success);
8266 if (!success)
8267 return false;
8268
8269 // Read the second operand.
8270 uint32_t val2 = ReadCoreReg(Rm, &success);
8271 if (!success)
8272 return false;
8273
8274 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008275 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008276
8277 EmulateInstruction::Context context;
8278 context.type = EmulateInstruction::eContextImmediate;
8279 context.SetNoArgs ();
8280
8281 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8282 return false;
8283 }
8284 return true;
8285}
8286
Johnny Chened32e7c2011-02-22 23:42:58 +00008287// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8288// the destination register. It can optionally update the condition flags based on the result.
8289bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008290EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008291{
8292#if 0
8293 // ARM pseudo code...
8294 if ConditionPassed() then
8295 EncodingSpecificOperations();
8296 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8297 if d == 15 then // Can only occur for ARM encoding
8298 ALUWritePC(result); // setflags is always FALSE here
8299 else
8300 R[d] = result;
8301 if setflags then
8302 APSR.N = result<31>;
8303 APSR.Z = IsZeroBit(result);
8304 APSR.C = carry;
8305 APSR.V = overflow;
8306#endif
8307
8308 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008309
8310 uint32_t Rd; // the destination register
8311 uint32_t Rn; // the first operand
8312 bool setflags;
8313 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8314 switch (encoding) {
8315 case eEncodingT1:
8316 Rd = Bits32(opcode, 2, 0);
8317 Rn = Bits32(opcode, 5, 3);
8318 setflags = !InITBlock();
8319 imm32 = 0;
8320 break;
8321 case eEncodingT2:
8322 Rd = Bits32(opcode, 11, 8);
8323 Rn = Bits32(opcode, 19, 16);
8324 setflags = BitIsSet(opcode, 20);
8325 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8326 if (BadReg(Rd) || BadReg(Rn))
8327 return false;
8328 break;
8329 case eEncodingA1:
8330 Rd = Bits32(opcode, 15, 12);
8331 Rn = Bits32(opcode, 19, 16);
8332 setflags = BitIsSet(opcode, 20);
8333 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8334 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8335 // TODO: Emulate SUBS PC, LR and related instructions.
8336 if (Rd == 15 && setflags)
8337 return false;
8338 break;
8339 default:
8340 return false;
8341 }
8342 // Read the register value from the operand register Rn.
8343 uint32_t reg_val = ReadCoreReg(Rn, &success);
8344 if (!success)
8345 return false;
8346
8347 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8348
8349 EmulateInstruction::Context context;
8350 context.type = EmulateInstruction::eContextImmediate;
8351 context.SetNoArgs ();
8352
8353 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8354 return false;
8355
8356 return true;
8357}
8358
8359// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8360// result to the destination register. It can optionally update the condition flags based on the result.
8361bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008362EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008363{
8364#if 0
8365 // ARM pseudo code...
8366 if ConditionPassed() then
8367 EncodingSpecificOperations();
8368 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8369 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8370 if d == 15 then // Can only occur for ARM encoding
8371 ALUWritePC(result); // setflags is always FALSE here
8372 else
8373 R[d] = result;
8374 if setflags then
8375 APSR.N = result<31>;
8376 APSR.Z = IsZeroBit(result);
8377 APSR.C = carry;
8378 APSR.V = overflow;
8379#endif
8380
8381 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008382
8383 uint32_t Rd; // the destination register
8384 uint32_t Rn; // the first operand
8385 uint32_t Rm; // the second operand
8386 bool setflags;
8387 ARM_ShifterType shift_t;
8388 uint32_t shift_n; // the shift applied to the value read from Rm
8389 switch (encoding) {
8390 case eEncodingT1:
8391 Rd = Bits32(opcode, 11, 8);
8392 Rn = Bits32(opcode, 19, 16);
8393 Rm = Bits32(opcode, 3, 0);
8394 setflags = BitIsSet(opcode, 20);
8395 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8396 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8397 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8398 return false;
8399 break;
8400 case eEncodingA1:
8401 Rd = Bits32(opcode, 15, 12);
8402 Rn = Bits32(opcode, 19, 16);
8403 Rm = Bits32(opcode, 3, 0);
8404 setflags = BitIsSet(opcode, 20);
8405 shift_n = DecodeImmShiftARM(opcode, shift_t);
8406 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8407 // TODO: Emulate SUBS PC, LR and related instructions.
8408 if (Rd == 15 && setflags)
8409 return false;
8410 break;
8411 default:
8412 return false;
8413 }
8414 // Read the register value from register Rn.
8415 uint32_t val1 = ReadCoreReg(Rn, &success);
8416 if (!success)
8417 return false;
8418
8419 // Read the register value from register Rm.
8420 uint32_t val2 = ReadCoreReg(Rm, &success);
8421 if (!success)
8422 return false;
8423
8424 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8425 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8426
8427 EmulateInstruction::Context context;
8428 context.type = EmulateInstruction::eContextImmediate;
8429 context.SetNoArgs();
8430 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8431 return false;
8432
8433 return true;
8434}
8435
Johnny Chen90e607b2011-02-23 00:07:09 +00008436// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8437// an immediate value, and writes the result to the destination register. It can optionally update the condition
8438// flags based on the result.
8439bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008440EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008441{
8442#if 0
8443 // ARM pseudo code...
8444 if ConditionPassed() then
8445 EncodingSpecificOperations();
8446 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8447 if d == 15 then
8448 ALUWritePC(result); // setflags is always FALSE here
8449 else
8450 R[d] = result;
8451 if setflags then
8452 APSR.N = result<31>;
8453 APSR.Z = IsZeroBit(result);
8454 APSR.C = carry;
8455 APSR.V = overflow;
8456#endif
8457
8458 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008459
8460 uint32_t Rd; // the destination register
8461 uint32_t Rn; // the first operand
8462 bool setflags;
8463 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8464 switch (encoding) {
8465 case eEncodingA1:
8466 Rd = Bits32(opcode, 15, 12);
8467 Rn = Bits32(opcode, 19, 16);
8468 setflags = BitIsSet(opcode, 20);
8469 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8470 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8471 // TODO: Emulate SUBS PC, LR and related instructions.
8472 if (Rd == 15 && setflags)
8473 return false;
8474 break;
8475 default:
8476 return false;
8477 }
8478 // Read the register value from the operand register Rn.
8479 uint32_t reg_val = ReadCoreReg(Rn, &success);
8480 if (!success)
8481 return false;
8482
8483 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8484
8485 EmulateInstruction::Context context;
8486 context.type = EmulateInstruction::eContextImmediate;
8487 context.SetNoArgs ();
8488
8489 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8490 return false;
8491
8492 return true;
8493}
8494
8495// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8496// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8497// condition flags based on the result.
8498bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008499EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008500{
8501#if 0
8502 // ARM pseudo code...
8503 if ConditionPassed() then
8504 EncodingSpecificOperations();
8505 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8506 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8507 if d == 15 then
8508 ALUWritePC(result); // setflags is always FALSE here
8509 else
8510 R[d] = result;
8511 if setflags then
8512 APSR.N = result<31>;
8513 APSR.Z = IsZeroBit(result);
8514 APSR.C = carry;
8515 APSR.V = overflow;
8516#endif
8517
8518 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008519
8520 uint32_t Rd; // the destination register
8521 uint32_t Rn; // the first operand
8522 uint32_t Rm; // the second operand
8523 bool setflags;
8524 ARM_ShifterType shift_t;
8525 uint32_t shift_n; // the shift applied to the value read from Rm
8526 switch (encoding) {
8527 case eEncodingA1:
8528 Rd = Bits32(opcode, 15, 12);
8529 Rn = Bits32(opcode, 19, 16);
8530 Rm = Bits32(opcode, 3, 0);
8531 setflags = BitIsSet(opcode, 20);
8532 shift_n = DecodeImmShiftARM(opcode, shift_t);
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 register Rn.
8542 uint32_t val1 = ReadCoreReg(Rn, &success);
8543 if (!success)
8544 return false;
8545
8546 // Read the register value from register Rm.
8547 uint32_t val2 = ReadCoreReg(Rm, &success);
8548 if (!success)
8549 return false;
8550
8551 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8552 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8553
8554 EmulateInstruction::Context context;
8555 context.type = EmulateInstruction::eContextImmediate;
8556 context.SetNoArgs();
8557 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8558 return false;
8559
8560 return true;
8561}
8562
Johnny Chen9b381772011-02-23 01:01:21 +00008563// Subtract with Carry (immediate) subtracts an immediate value and the value of
8564// NOT (Carry flag) from a register value, and writes the result to the destination register.
8565// It can optionally update the condition flags based on the result.
8566bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008567EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008568{
8569#if 0
8570 // ARM pseudo code...
8571 if ConditionPassed() then
8572 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008573 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008574 if d == 15 then // Can only occur for ARM encoding
8575 ALUWritePC(result); // setflags is always FALSE here
8576 else
8577 R[d] = result;
8578 if setflags then
8579 APSR.N = result<31>;
8580 APSR.Z = IsZeroBit(result);
8581 APSR.C = carry;
8582 APSR.V = overflow;
8583#endif
8584
8585 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008586
8587 uint32_t Rd; // the destination register
8588 uint32_t Rn; // the first operand
8589 bool setflags;
8590 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8591 switch (encoding) {
8592 case eEncodingT1:
8593 Rd = Bits32(opcode, 11, 8);
8594 Rn = Bits32(opcode, 19, 16);
8595 setflags = BitIsSet(opcode, 20);
8596 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8597 if (BadReg(Rd) || BadReg(Rn))
8598 return false;
8599 break;
8600 case eEncodingA1:
8601 Rd = Bits32(opcode, 15, 12);
8602 Rn = Bits32(opcode, 19, 16);
8603 setflags = BitIsSet(opcode, 20);
8604 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8605 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8606 // TODO: Emulate SUBS PC, LR and related instructions.
8607 if (Rd == 15 && setflags)
8608 return false;
8609 break;
8610 default:
8611 return false;
8612 }
8613 // Read the register value from the operand register Rn.
8614 uint32_t reg_val = ReadCoreReg(Rn, &success);
8615 if (!success)
8616 return false;
8617
8618 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8619
8620 EmulateInstruction::Context context;
8621 context.type = EmulateInstruction::eContextImmediate;
8622 context.SetNoArgs ();
8623
8624 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8625 return false;
8626
8627 return true;
8628}
8629
8630// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8631// NOT (Carry flag) from a register value, and writes the result to the destination register.
8632// It can optionally update the condition flags based on the result.
8633bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008634EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008635{
8636#if 0
8637 // ARM pseudo code...
8638 if ConditionPassed() then
8639 EncodingSpecificOperations();
8640 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8641 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8642 if d == 15 then // Can only occur for ARM encoding
8643 ALUWritePC(result); // setflags is always FALSE here
8644 else
8645 R[d] = result;
8646 if setflags then
8647 APSR.N = result<31>;
8648 APSR.Z = IsZeroBit(result);
8649 APSR.C = carry;
8650 APSR.V = overflow;
8651#endif
8652
8653 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008654
8655 uint32_t Rd; // the destination register
8656 uint32_t Rn; // the first operand
8657 uint32_t Rm; // the second operand
8658 bool setflags;
8659 ARM_ShifterType shift_t;
8660 uint32_t shift_n; // the shift applied to the value read from Rm
8661 switch (encoding) {
8662 case eEncodingT1:
8663 Rd = Rn = Bits32(opcode, 2, 0);
8664 Rm = Bits32(opcode, 5, 3);
8665 setflags = !InITBlock();
8666 shift_t = SRType_LSL;
8667 shift_n = 0;
8668 break;
8669 case eEncodingT2:
8670 Rd = Bits32(opcode, 11, 8);
8671 Rn = Bits32(opcode, 19, 16);
8672 Rm = Bits32(opcode, 3, 0);
8673 setflags = BitIsSet(opcode, 20);
8674 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8675 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8676 return false;
8677 break;
8678 case eEncodingA1:
8679 Rd = Bits32(opcode, 15, 12);
8680 Rn = Bits32(opcode, 19, 16);
8681 Rm = Bits32(opcode, 3, 0);
8682 setflags = BitIsSet(opcode, 20);
8683 shift_n = DecodeImmShiftARM(opcode, shift_t);
8684 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8685 // TODO: Emulate SUBS PC, LR and related instructions.
8686 if (Rd == 15 && setflags)
8687 return false;
8688 break;
8689 default:
8690 return false;
8691 }
8692 // Read the register value from register Rn.
8693 uint32_t val1 = ReadCoreReg(Rn, &success);
8694 if (!success)
8695 return false;
8696
8697 // Read the register value from register Rm.
8698 uint32_t val2 = ReadCoreReg(Rm, &success);
8699 if (!success)
8700 return false;
8701
8702 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8703 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8704
8705 EmulateInstruction::Context context;
8706 context.type = EmulateInstruction::eContextImmediate;
8707 context.SetNoArgs();
8708 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8709 return false;
8710
8711 return true;
8712}
8713
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008714// This instruction subtracts an immediate value from a register value, and writes the result
8715// to the destination register. It can optionally update the condition flags based on the result.
8716bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008717EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008718{
8719#if 0
8720 // ARM pseudo code...
8721 if ConditionPassed() then
8722 EncodingSpecificOperations();
8723 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8724 R[d] = result;
8725 if setflags then
8726 APSR.N = result<31>;
8727 APSR.Z = IsZeroBit(result);
8728 APSR.C = carry;
8729 APSR.V = overflow;
8730#endif
8731
8732 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008733
8734 uint32_t Rd; // the destination register
8735 uint32_t Rn; // the first operand
8736 bool setflags;
8737 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8738 switch (encoding) {
8739 case eEncodingT1:
8740 Rd = Bits32(opcode, 2, 0);
8741 Rn = Bits32(opcode, 5, 3);
8742 setflags = !InITBlock();
8743 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8744 break;
8745 case eEncodingT2:
8746 Rd = Rn = Bits32(opcode, 10, 8);
8747 setflags = !InITBlock();
8748 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8749 break;
8750 case eEncodingT3:
8751 Rd = Bits32(opcode, 11, 8);
8752 Rn = Bits32(opcode, 19, 16);
8753 setflags = BitIsSet(opcode, 20);
8754 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8755
8756 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8757 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008758 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008759
8760 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8761 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008762 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008763
8764 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8765 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8766 return false;
8767 break;
8768 case eEncodingT4:
8769 Rd = Bits32(opcode, 11, 8);
8770 Rn = Bits32(opcode, 19, 16);
8771 setflags = BitIsSet(opcode, 20);
8772 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8773
8774 // if Rn == '1111' then SEE ADR;
8775 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008776 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008777
8778 // if Rn == '1101' then SEE SUB (SP minus immediate);
8779 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008780 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008781
8782 if (BadReg(Rd))
8783 return false;
8784 break;
8785 default:
8786 return false;
8787 }
8788 // Read the register value from the operand register Rn.
8789 uint32_t reg_val = ReadCoreReg(Rn, &success);
8790 if (!success)
8791 return false;
8792
8793 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8794
8795 EmulateInstruction::Context context;
8796 context.type = EmulateInstruction::eContextImmediate;
8797 context.SetNoArgs ();
8798
8799 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8800 return false;
8801
8802 return true;
8803}
8804
8805// This instruction subtracts an immediate value from a register value, and writes the result
8806// to the destination register. It can optionally update the condition flags based on the result.
8807bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008808EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008809{
8810#if 0
8811 // ARM pseudo code...
8812 if ConditionPassed() then
8813 EncodingSpecificOperations();
8814 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8815 if d == 15 then
8816 ALUWritePC(result); // setflags is always FALSE here
8817 else
8818 R[d] = result;
8819 if setflags then
8820 APSR.N = result<31>;
8821 APSR.Z = IsZeroBit(result);
8822 APSR.C = carry;
8823 APSR.V = overflow;
8824#endif
8825
8826 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008827
8828 uint32_t Rd; // the destination register
8829 uint32_t Rn; // the first operand
8830 bool setflags;
8831 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8832 switch (encoding) {
8833 case eEncodingA1:
8834 Rd = Bits32(opcode, 15, 12);
8835 Rn = Bits32(opcode, 19, 16);
8836 setflags = BitIsSet(opcode, 20);
8837 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8838
8839 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8840 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008841 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008842
8843 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8844 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008845 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008846
8847 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8848 // TODO: Emulate SUBS PC, LR and related instructions.
8849 if (Rd == 15 && setflags)
8850 return false;
8851 break;
8852 default:
8853 return false;
8854 }
8855 // Read the register value from the operand register Rn.
8856 uint32_t reg_val = ReadCoreReg(Rn, &success);
8857 if (!success)
8858 return false;
8859
8860 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8861
8862 EmulateInstruction::Context context;
8863 context.type = EmulateInstruction::eContextImmediate;
8864 context.SetNoArgs ();
8865
8866 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8867 return false;
8868
8869 return true;
8870}
8871
Johnny Chen2115b412011-02-21 23:42:44 +00008872// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8873// immediate value. It updates the condition flags based on the result, and discards the result.
8874bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008875EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008876{
8877#if 0
8878 // ARM pseudo code...
8879 if ConditionPassed() then
8880 EncodingSpecificOperations();
8881 result = R[n] EOR imm32;
8882 APSR.N = result<31>;
8883 APSR.Z = IsZeroBit(result);
8884 APSR.C = carry;
8885 // APSR.V unchanged
8886#endif
8887
8888 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008889
Greg Clayton7bc39082011-03-24 23:53:38 +00008890 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008891 {
8892 uint32_t Rn;
8893 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8894 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8895 switch (encoding)
8896 {
8897 case eEncodingT1:
8898 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008899 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008900 if (BadReg(Rn))
8901 return false;
8902 break;
8903 case eEncodingA1:
8904 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008905 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008906 break;
8907 default:
8908 return false;
8909 }
8910
8911 // Read the first operand.
8912 uint32_t val1 = ReadCoreReg(Rn, &success);
8913 if (!success)
8914 return false;
8915
8916 uint32_t result = val1 ^ imm32;
8917
8918 EmulateInstruction::Context context;
8919 context.type = EmulateInstruction::eContextImmediate;
8920 context.SetNoArgs ();
8921
8922 if (!WriteFlags(context, result, carry))
8923 return false;
8924 }
8925 return true;
8926}
8927
8928// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8929// optionally-shifted register value. It updates the condition flags based on the result, and discards
8930// the result.
8931bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008932EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008933{
8934#if 0
8935 // ARM pseudo code...
8936 if ConditionPassed() then
8937 EncodingSpecificOperations();
8938 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8939 result = R[n] EOR shifted;
8940 APSR.N = result<31>;
8941 APSR.Z = IsZeroBit(result);
8942 APSR.C = carry;
8943 // APSR.V unchanged
8944#endif
8945
8946 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008947
Greg Clayton7bc39082011-03-24 23:53:38 +00008948 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008949 {
8950 uint32_t Rn, Rm;
8951 ARM_ShifterType shift_t;
8952 uint32_t shift_n; // the shift applied to the value read from Rm
8953 uint32_t carry;
8954 switch (encoding)
8955 {
8956 case eEncodingT1:
8957 Rn = Bits32(opcode, 19, 16);
8958 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008959 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008960 if (BadReg(Rn) || BadReg(Rm))
8961 return false;
8962 break;
8963 case eEncodingA1:
8964 Rn = Bits32(opcode, 19, 16);
8965 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008966 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008967 break;
8968 default:
8969 return false;
8970 }
8971
8972 // Read the first operand.
8973 uint32_t val1 = ReadCoreReg(Rn, &success);
8974 if (!success)
8975 return false;
8976
8977 // Read the second operand.
8978 uint32_t val2 = ReadCoreReg(Rm, &success);
8979 if (!success)
8980 return false;
8981
8982 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8983 uint32_t result = val1 ^ shifted;
8984
8985 EmulateInstruction::Context context;
8986 context.type = EmulateInstruction::eContextImmediate;
8987 context.SetNoArgs ();
8988
8989 if (!WriteFlags(context, result, carry))
8990 return false;
8991 }
8992 return true;
8993}
8994
Johnny Chende3cce32011-02-21 21:24:49 +00008995// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8996// It updates the condition flags based on the result, and discards the result.
8997bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008998EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00008999{
9000#if 0
9001 // ARM pseudo code...
9002 if ConditionPassed() then
9003 EncodingSpecificOperations();
9004 result = R[n] AND imm32;
9005 APSR.N = result<31>;
9006 APSR.Z = IsZeroBit(result);
9007 APSR.C = carry;
9008 // APSR.V unchanged
9009#endif
9010
9011 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009012
Greg Clayton7bc39082011-03-24 23:53:38 +00009013 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009014 {
9015 uint32_t Rn;
9016 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9017 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9018 switch (encoding)
9019 {
9020 case eEncodingT1:
9021 Rn = Bits32(opcode, 19, 16);
9022 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9023 if (BadReg(Rn))
9024 return false;
9025 break;
9026 case eEncodingA1:
9027 Rn = Bits32(opcode, 19, 16);
9028 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9029 break;
9030 default:
9031 return false;
9032 }
9033
9034 // Read the first operand.
9035 uint32_t val1 = ReadCoreReg(Rn, &success);
9036 if (!success)
9037 return false;
9038
9039 uint32_t result = val1 & imm32;
9040
9041 EmulateInstruction::Context context;
9042 context.type = EmulateInstruction::eContextImmediate;
9043 context.SetNoArgs ();
9044
9045 if (!WriteFlags(context, result, carry))
9046 return false;
9047 }
9048 return true;
9049}
9050
9051// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9052// It updates the condition flags based on the result, and discards the result.
9053bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009054EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009055{
9056#if 0
9057 // ARM pseudo code...
9058 if ConditionPassed() then
9059 EncodingSpecificOperations();
9060 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9061 result = R[n] AND shifted;
9062 APSR.N = result<31>;
9063 APSR.Z = IsZeroBit(result);
9064 APSR.C = carry;
9065 // APSR.V unchanged
9066#endif
9067
9068 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009069
Greg Clayton7bc39082011-03-24 23:53:38 +00009070 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009071 {
9072 uint32_t Rn, Rm;
9073 ARM_ShifterType shift_t;
9074 uint32_t shift_n; // the shift applied to the value read from Rm
9075 uint32_t carry;
9076 switch (encoding)
9077 {
9078 case eEncodingT1:
9079 Rn = Bits32(opcode, 2, 0);
9080 Rm = Bits32(opcode, 5, 3);
9081 shift_t = SRType_LSL;
9082 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009083 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009084 case eEncodingT2:
9085 Rn = Bits32(opcode, 19, 16);
9086 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009087 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009088 if (BadReg(Rn) || BadReg(Rm))
9089 return false;
9090 break;
9091 case eEncodingA1:
9092 Rn = Bits32(opcode, 19, 16);
9093 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009094 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009095 break;
9096 default:
9097 return false;
9098 }
9099
9100 // Read the first operand.
9101 uint32_t val1 = ReadCoreReg(Rn, &success);
9102 if (!success)
9103 return false;
9104
9105 // Read the second operand.
9106 uint32_t val2 = ReadCoreReg(Rm, &success);
9107 if (!success)
9108 return false;
9109
9110 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9111 uint32_t result = val1 & shifted;
9112
9113 EmulateInstruction::Context context;
9114 context.type = EmulateInstruction::eContextImmediate;
9115 context.SetNoArgs ();
9116
9117 if (!WriteFlags(context, result, carry))
9118 return false;
9119 }
9120 return true;
9121}
9122
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009123EmulateInstructionARM::ARMOpcode*
9124EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009125{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009126 static ARMOpcode
9127 g_arm_opcodes[] =
9128 {
9129 //----------------------------------------------------------------------
9130 // Prologue instructions
9131 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009132
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009133 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009134 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9135 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009136
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009137 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009138 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009139 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009140 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009141 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9142 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009143 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009144
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009145 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009146 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009147
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009148 // push one register
9149 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009150 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009151
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009152 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009153 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9154 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009155
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009156 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009157 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009158 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009159
Johnny Chen9f687722011-02-18 00:02:28 +00009160 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9161 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009162 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009163 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9164
9165 //----------------------------------------------------------------------
9166 // Supervisor Call (previously Software Interrupt)
9167 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009168 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9169
9170 //----------------------------------------------------------------------
9171 // Branch instructions
9172 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009173 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009174 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9175 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9176 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9177 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009178 // for example, "bx lr"
9179 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009180 // bxj
9181 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009182
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009183 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009184 // Data-processing instructions
9185 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009186 // adc (immediate)
9187 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9188 // adc (register)
9189 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009190 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009191 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009192 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009193 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009194 // adr
9195 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9196 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009197 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009198 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009199 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009200 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009201 // bic (immediate)
9202 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9203 // bic (register)
9204 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009205 // eor (immediate)
9206 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9207 // eor (register)
9208 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009209 // orr (immediate)
9210 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9211 // orr (register)
9212 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009213 // rsb (immediate)
9214 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9215 // rsb (register)
9216 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009217 // rsc (immediate)
9218 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9219 // rsc (register)
9220 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009221 // sbc (immediate)
9222 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9223 // sbc (register)
9224 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009225 // sub (immediate, ARM)
9226 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009227 // sub (sp minus immediate)
9228 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009229 // teq (immediate)
9230 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9231 // teq (register)
9232 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009233 // tst (immediate)
9234 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9235 // tst (register)
9236 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9237
9238
Johnny Chen01d61572011-02-25 00:23:25 +00009239 // mov (register)
9240 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009241 // mvn (immediate)
9242 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9243 // mvn (register)
9244 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009245 // cmn (immediate)
9246 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9247 // cmn (register)
9248 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009249 // cmp (immediate)
9250 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9251 // cmp (register)
9252 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009253 // asr (immediate)
9254 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009255 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009256 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009257 // lsl (immediate)
9258 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9259 // lsl (register)
9260 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9261 // lsr (immediate)
9262 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9263 // lsr (register)
9264 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009265 // rrx is a special case encoding of ror (immediate)
9266 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9267 // ror (immediate)
9268 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9269 // ror (register)
9270 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009271 // mul
9272 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009273
9274 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009275 // Load instructions
9276 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009277 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009278 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009279 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009280 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009281 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009282 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009283 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009284 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009285 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009286 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009287 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009288 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009289 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009290 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009291 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9292 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009293
9294 //----------------------------------------------------------------------
9295 // Store instructions
9296 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009297 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009298 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009299 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009300 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009301 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009302 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009303
Caroline Tice6bf65162011-03-03 17:42:58 +00009304 //----------------------------------------------------------------------
9305 // Other instructions
9306 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009307 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009308 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009309 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009310 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9311 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009312
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009313 };
9314 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9315
9316 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9317 {
9318 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9319 return &g_arm_opcodes[i];
9320 }
9321 return NULL;
9322}
Greg Clayton64c84432011-01-21 22:02:52 +00009323
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009324
9325EmulateInstructionARM::ARMOpcode*
9326EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009327{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009328
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009329 static ARMOpcode
9330 g_thumb_opcodes[] =
9331 {
9332 //----------------------------------------------------------------------
9333 // Prologue instructions
9334 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009335
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009336 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009337 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9338 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9339 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009340
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009341 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009342 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009343 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009344 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009345 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009346 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009347
Johnny Chen864a8e82011-02-18 00:07:39 +00009348 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009349 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009350
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009351 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009352 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009353 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009354 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9355 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009356
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009357 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009358 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9359 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009360
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009361 //----------------------------------------------------------------------
9362 // Epilogue instructions
9363 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009364
Caroline Ticee2212882011-03-22 22:38:28 +00009365 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009366 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009367 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9368 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9369 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009370 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9371 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009372
9373 //----------------------------------------------------------------------
9374 // Supervisor Call (previously Software Interrupt)
9375 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009376 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9377
9378 //----------------------------------------------------------------------
9379 // If Then makes up to four following instructions conditional.
9380 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009381 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9382
9383 //----------------------------------------------------------------------
9384 // Branch instructions
9385 //----------------------------------------------------------------------
9386 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9387 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +00009388 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009389 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009390 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009391 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009392 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009393 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009394 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009395 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009396 // for example, "bx lr"
9397 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009398 // bxj
9399 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009400 // compare and branch
9401 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009402 // table branch byte
9403 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9404 // table branch halfword
9405 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009406
9407 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009408 // Data-processing instructions
9409 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009410 // adc (immediate)
9411 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9412 // adc (register)
9413 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9414 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9415 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009416 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009417 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009418 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009419 // adr
9420 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9421 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9422 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009423 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009424 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009425 // and (register)
9426 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9427 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009428 // bic (immediate)
9429 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9430 // bic (register)
9431 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9432 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009433 // eor (immediate)
9434 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9435 // eor (register)
9436 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9437 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009438 // orr (immediate)
9439 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9440 // orr (register)
9441 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9442 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009443 // rsb (immediate)
9444 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9445 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9446 // rsb (register)
9447 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009448 // sbc (immediate)
9449 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9450 // sbc (register)
9451 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9452 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009453 // add (immediate, Thumb)
9454 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9455 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9456 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9457 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009458 // sub (immediate, Thumb)
9459 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9460 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9461 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9462 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009463 // sub (sp minus immediate)
9464 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9465 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009466 // teq (immediate)
9467 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9468 // teq (register)
9469 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009470 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009471 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009472 // tst (register)
9473 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9474 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9475
Johnny Chen7c5234d2011-02-18 23:41:11 +00009476
Johnny Chen338bf542011-02-10 19:29:03 +00009477 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009478 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009479 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009480 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009481 // mov{s}<c>.w <Rd>, <Rm>
9482 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009483 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009484 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9485 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009486 // mvn (immediate)
9487 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9488 // mvn (register)
9489 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9490 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009491 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009492 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009493 // cmn (register)
9494 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009495 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009496 // cmp (immediate)
9497 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009498 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009499 // cmp (register) (Rn and Rm both from r0-r7)
9500 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9501 // cmp (register) (Rn and Rm not both from r0-r7)
9502 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009503 // asr (immediate)
9504 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009505 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009506 // asr (register)
9507 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9508 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009509 // lsl (immediate)
9510 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9511 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9512 // lsl (register)
9513 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9514 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9515 // lsr (immediate)
9516 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9517 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9518 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009519 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009520 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009521 // rrx is a special case encoding of ror (immediate)
9522 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9523 // ror (immediate)
9524 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9525 // ror (register)
9526 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9527 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009528 // mul
9529 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9530 // mul
9531 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009532
Johnny Chen26863dc2011-02-09 23:43:29 +00009533 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009534 // Load instructions
9535 //----------------------------------------------------------------------
9536 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009537 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009538 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticebaf1f642011-03-24 19:23:45 +00009539 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9540 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
9541 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
9542 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
9543 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009544 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009545 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9546 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009547 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9548 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9549 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009550 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009551 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9552 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009553 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9554 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9555 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009556 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009557 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9558 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009559 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9560 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009561 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009562 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9563 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009564 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9565 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009566 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009567 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9568 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009569
9570 //----------------------------------------------------------------------
9571 // Store instructions
9572 //----------------------------------------------------------------------
9573 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009574 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009575 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009576 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9577 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9578 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9579 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9580 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9581 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9582 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9583 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009584 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009585 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9586 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009587
9588 //----------------------------------------------------------------------
9589 // Other instructions
9590 //----------------------------------------------------------------------
9591 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009592 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9593 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009594 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9595 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009596 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9597 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009598 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9599 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9600 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009601
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009602 };
9603
9604 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9605 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9606 {
9607 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9608 return &g_thumb_opcodes[i];
9609 }
9610 return NULL;
9611}
Greg Clayton64c84432011-01-21 22:02:52 +00009612
Greg Clayton31e2a382011-01-30 20:03:56 +00009613bool
Greg Clayton395fc332011-02-15 21:59:32 +00009614EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009615{
9616 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009617 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009618 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009619 {
Greg Clayton395fc332011-02-15 21:59:32 +00009620 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9621 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9622 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9623 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9624 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9625 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9626 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9627 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9628 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9629 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009630 }
9631 return m_arm_isa != 0;
9632}
9633
9634
Greg Clayton64c84432011-01-21 22:02:52 +00009635bool
9636EmulateInstructionARM::ReadInstruction ()
9637{
9638 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +00009639 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009640 if (success)
9641 {
9642 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9643 if (success)
9644 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009645 Context read_inst_context;
9646 read_inst_context.type = eContextReadOpcode;
9647 read_inst_context.SetNoArgs ();
9648
Greg Claytonb3448432011-03-24 21:19:54 +00009649 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +00009650 {
Greg Claytonb3448432011-03-24 21:19:54 +00009651 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009652 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009653
9654 if (success)
9655 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009656 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +00009657 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009658 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009659 }
9660 else
9661 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009662 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009663 }
9664 }
9665 }
9666 else
9667 {
Greg Claytonb3448432011-03-24 21:19:54 +00009668 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +00009669 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009670 }
9671 }
9672 }
9673 if (!success)
9674 {
Greg Claytonb3448432011-03-24 21:19:54 +00009675 m_opcode_mode = eModeInvalid;
9676 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +00009677 }
9678 return success;
9679}
9680
Johnny Chenee9b1f72011-02-09 01:00:31 +00009681uint32_t
9682EmulateInstructionARM::ArchVersion ()
9683{
9684 return m_arm_isa;
9685}
9686
Greg Clayton64c84432011-01-21 22:02:52 +00009687bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009688EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009689{
Greg Claytonb3448432011-03-24 21:19:54 +00009690 if (m_opcode_cpsr == 0)
Greg Clayton64c84432011-01-21 22:02:52 +00009691 return false;
9692
Greg Clayton7bc39082011-03-24 23:53:38 +00009693 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009694
9695 if (cond == UINT32_MAX)
9696 return false;
9697
9698 bool result = false;
9699 switch (UnsignedBits(cond, 3, 1))
9700 {
Greg Claytonb3448432011-03-24 21:19:54 +00009701 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
9702 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
9703 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
9704 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
9705 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 +00009706 case 5:
9707 {
Greg Claytonb3448432011-03-24 21:19:54 +00009708 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9709 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +00009710 result = n == v;
9711 }
9712 break;
9713 case 6:
9714 {
Greg Claytonb3448432011-03-24 21:19:54 +00009715 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9716 bool v = (m_opcode_cpsr & MASK_CPSR_V);
9717 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +00009718 }
9719 break;
9720 case 7:
9721 result = true;
9722 break;
9723 }
9724
9725 if (cond & 1)
9726 result = !result;
9727 return result;
9728}
9729
Johnny Chen9ee056b2011-02-08 00:06:35 +00009730uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +00009731EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009732{
Greg Claytonb3448432011-03-24 21:19:54 +00009733 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009734 {
9735 default:
9736 case eModeInvalid:
9737 break;
9738
9739 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +00009740 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009741
9742 case eModeThumb:
9743 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9744 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +00009745 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009746 const uint32_t byte_size = m_opcode.GetByteSize();
9747 if (byte_size == 2)
9748 {
9749 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
9750 return Bits32(opcode, 11, 7);
9751 }
9752 else
9753 {
9754 assert (byte_size == 4);
9755 if (Bits32(opcode, 31, 27) == 0x1e &&
9756 Bits32(opcode, 15, 14) == 0x02 &&
9757 Bits32(opcode, 12, 12) == 0x00 &&
9758 Bits32(opcode, 25, 22) <= 0x0d)
9759 {
9760 return Bits32(opcode, 25, 22);
9761 }
9762 }
9763
9764 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +00009765 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009766 }
9767 return UINT32_MAX; // Return invalid value
9768}
9769
Johnny Chen9ee056b2011-02-08 00:06:35 +00009770bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009771EmulateInstructionARM::InITBlock()
9772{
9773 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9774}
9775
9776bool
9777EmulateInstructionARM::LastInITBlock()
9778{
9779 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9780}
9781
Caroline Ticeb27771d2011-03-03 22:37:46 +00009782bool
9783EmulateInstructionARM::BadMode (uint32_t mode)
9784{
9785
9786 switch (mode)
9787 {
9788 case 16: return false; // '10000'
9789 case 17: return false; // '10001'
9790 case 18: return false; // '10010'
9791 case 19: return false; // '10011'
9792 case 22: return false; // '10110'
9793 case 23: return false; // '10111'
9794 case 27: return false; // '11011'
9795 case 31: return false; // '11111'
9796 default: return true;
9797 }
9798 return true;
9799}
9800
9801bool
9802EmulateInstructionARM::CurrentModeIsPrivileged ()
9803{
Greg Claytonb3448432011-03-24 21:19:54 +00009804 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009805
9806 if (BadMode (mode))
9807 return false;
9808
9809 if (mode == 16)
9810 return false;
9811
9812 return true;
9813}
9814
9815void
9816EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9817{
9818 bool privileged = CurrentModeIsPrivileged();
9819
9820 uint32_t tmp_cpsr = 0;
9821
Greg Claytonb3448432011-03-24 21:19:54 +00009822 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009823
9824 if (BitIsSet (bytemask, 3))
9825 {
9826 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
9827 if (affect_execstate)
9828 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
9829 }
9830
9831 if (BitIsSet (bytemask, 2))
9832 {
9833 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
9834 }
9835
9836 if (BitIsSet (bytemask, 1))
9837 {
9838 if (affect_execstate)
9839 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
9840 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
9841 if (privileged)
9842 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
9843 }
9844
9845 if (BitIsSet (bytemask, 0))
9846 {
9847 if (privileged)
9848 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
9849 if (affect_execstate)
9850 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
9851 if (privileged)
9852 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
9853 }
9854
Greg Claytonb3448432011-03-24 21:19:54 +00009855 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +00009856}
9857
9858
Johnny Chen098ae2d2011-02-12 00:50:05 +00009859bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009860EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9861{
9862 addr_t target;
9863
Johnny Chenee9b1f72011-02-09 01:00:31 +00009864 // Check the current instruction set.
9865 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009866 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009867 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009868 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009869
Johnny Chen9ee056b2011-02-08 00:06:35 +00009870 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009871 return false;
9872
9873 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009874}
9875
9876// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9877bool
Johnny Chen668b4512011-02-15 21:08:58 +00009878EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009879{
9880 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009881 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9882 // we want to record it and issue a WriteRegister callback so the clients
9883 // can track the mode changes accordingly.
9884 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009885
9886 if (BitIsSet(addr, 0))
9887 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009888 if (CurrentInstrSet() != eModeThumb)
9889 {
9890 SelectInstrSet(eModeThumb);
9891 cpsr_changed = true;
9892 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009893 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009894 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009895 }
9896 else if (BitIsClear(addr, 1))
9897 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009898 if (CurrentInstrSet() != eModeARM)
9899 {
9900 SelectInstrSet(eModeARM);
9901 cpsr_changed = true;
9902 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009903 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009904 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009905 }
9906 else
9907 return false; // address<1:0> == '10' => UNPREDICTABLE
9908
Johnny Chen0f309db2011-02-09 19:11:32 +00009909 if (cpsr_changed)
9910 {
Johnny Chen558133b2011-02-09 23:59:17 +00009911 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009912 return false;
9913 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009914 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009915 return false;
9916
9917 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009918}
Greg Clayton64c84432011-01-21 22:02:52 +00009919
Johnny Chenee9b1f72011-02-09 01:00:31 +00009920// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9921bool
Johnny Chen668b4512011-02-15 21:08:58 +00009922EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009923{
9924 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009925 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009926 else
9927 return BranchWritePC((const Context)context, addr);
9928}
9929
Johnny Chen26863dc2011-02-09 23:43:29 +00009930// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9931bool
Johnny Chen668b4512011-02-15 21:08:58 +00009932EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009933{
9934 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009935 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009936 else
9937 return BranchWritePC((const Context)context, addr);
9938}
9939
Johnny Chenee9b1f72011-02-09 01:00:31 +00009940EmulateInstructionARM::Mode
9941EmulateInstructionARM::CurrentInstrSet ()
9942{
Greg Claytonb3448432011-03-24 21:19:54 +00009943 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009944}
9945
Greg Claytonb3448432011-03-24 21:19:54 +00009946// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009947// ReadInstruction() is performed. This function has a side effect of updating
9948// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009949bool
9950EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9951{
Greg Claytonb3448432011-03-24 21:19:54 +00009952 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009953 switch (arm_or_thumb)
9954 {
9955 default:
9956 return false;
9957 eModeARM:
9958 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009959 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009960 break;
9961 eModeThumb:
9962 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009963 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009964 break;
9965 }
9966 return true;
9967}
9968
Johnny Chenef21b592011-02-10 01:52:38 +00009969// This function returns TRUE if the processor currently provides support for
9970// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9971// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9972bool
9973EmulateInstructionARM::UnalignedSupport()
9974{
9975 return (ArchVersion() >= ARMv7);
9976}
9977
Johnny Chenbf6ad172011-02-11 01:29:53 +00009978// The main addition and subtraction instructions can produce status information
9979// about both unsigned carry and signed overflow conditions. This status
9980// information can be used to synthesize multi-word additions and subtractions.
9981EmulateInstructionARM::AddWithCarryResult
9982EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9983{
9984 uint32_t result;
9985 uint8_t carry_out;
9986 uint8_t overflow;
9987
9988 uint64_t unsigned_sum = x + y + carry_in;
9989 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9990
9991 result = UnsignedBits(unsigned_sum, 31, 0);
9992 carry_out = (result == unsigned_sum ? 0 : 1);
9993 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9994
9995 AddWithCarryResult res = { result, carry_out, overflow };
9996 return res;
9997}
9998
Johnny Chen157b9592011-02-18 21:13:05 +00009999uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010000EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010001{
Johnny Chene39f22d2011-02-19 01:36:13 +000010002 uint32_t reg_kind, reg_num;
10003 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010004 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010005 case SP_REG:
10006 reg_kind = eRegisterKindGeneric;
10007 reg_num = LLDB_REGNUM_GENERIC_SP;
10008 break;
10009 case LR_REG:
10010 reg_kind = eRegisterKindGeneric;
10011 reg_num = LLDB_REGNUM_GENERIC_RA;
10012 break;
10013 case PC_REG:
10014 reg_kind = eRegisterKindGeneric;
10015 reg_num = LLDB_REGNUM_GENERIC_PC;
10016 break;
10017 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010018 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010019 {
10020 reg_kind = eRegisterKindDWARF;
10021 reg_num = dwarf_r0 + num;
10022 }
Johnny Chen157b9592011-02-18 21:13:05 +000010023 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010024 {
10025 assert(0 && "Invalid register number");
10026 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010027 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010028 }
10029 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010030 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010031
10032 // Read our register.
10033 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10034
10035 // When executing an ARM instruction , PC reads as the address of the current
10036 // instruction plus 8.
10037 // When executing a Thumb instruction , PC reads as the address of the current
10038 // instruction plus 4.
10039 if (num == 15)
10040 {
10041 if (CurrentInstrSet() == eModeARM)
10042 val += 8;
10043 else
10044 val += 4;
10045 }
Johnny Chen157b9592011-02-18 21:13:05 +000010046
10047 return val;
10048}
10049
Johnny Chenca67d1c2011-02-17 01:35:27 +000010050// Write the result to the ARM core register Rd, and optionally update the
10051// condition flags based on the result.
10052//
10053// This helper method tries to encapsulate the following pseudocode from the
10054// ARM Architecture Reference Manual:
10055//
10056// if d == 15 then // Can only occur for encoding A1
10057// ALUWritePC(result); // setflags is always FALSE here
10058// else
10059// R[d] = result;
10060// if setflags then
10061// APSR.N = result<31>;
10062// APSR.Z = IsZeroBit(result);
10063// APSR.C = carry;
10064// // APSR.V unchanged
10065//
10066// In the above case, the API client does not pass in the overflow arg, which
10067// defaults to ~0u.
10068bool
Johnny Chen10530c22011-02-17 22:37:12 +000010069EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10070 const uint32_t result,
10071 const uint32_t Rd,
10072 bool setflags,
10073 const uint32_t carry,
10074 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010075{
10076 if (Rd == 15)
10077 {
10078 if (!ALUWritePC (context, result))
10079 return false;
10080 }
10081 else
10082 {
Johnny Chena695f952011-02-23 21:24:25 +000010083 uint32_t reg_kind, reg_num;
10084 switch (Rd)
10085 {
10086 case SP_REG:
10087 reg_kind = eRegisterKindGeneric;
10088 reg_num = LLDB_REGNUM_GENERIC_SP;
10089 break;
10090 case LR_REG:
10091 reg_kind = eRegisterKindGeneric;
10092 reg_num = LLDB_REGNUM_GENERIC_RA;
10093 break;
10094 default:
10095 reg_kind = eRegisterKindDWARF;
10096 reg_num = dwarf_r0 + Rd;
10097 }
10098 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010099 return false;
10100 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010101 return WriteFlags (context, result, carry, overflow);
10102 }
10103 return true;
10104}
10105
10106// This helper method tries to encapsulate the following pseudocode from the
10107// ARM Architecture Reference Manual:
10108//
10109// APSR.N = result<31>;
10110// APSR.Z = IsZeroBit(result);
10111// APSR.C = carry;
10112// APSR.V = overflow
10113//
10114// Default arguments can be specified for carry and overflow parameters, which means
10115// not to update the respective flags.
10116bool
10117EmulateInstructionARM::WriteFlags (Context &context,
10118 const uint32_t result,
10119 const uint32_t carry,
10120 const uint32_t overflow)
10121{
Greg Claytonb3448432011-03-24 21:19:54 +000010122 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010123 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10124 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010125 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010126 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010127 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010128 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000010129 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000010130 {
10131 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10132 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010133 }
10134 return true;
10135}
10136
Greg Clayton64c84432011-01-21 22:02:52 +000010137bool
10138EmulateInstructionARM::EvaluateInstruction ()
10139{
Johnny Chenc315f862011-02-05 00:46:10 +000010140 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000010141 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000010142 m_it_session.ITAdvance();
10143
Greg Clayton64c84432011-01-21 22:02:52 +000010144 return false;
10145}