blob: 57b4075e09f8de54847fa8ff4b26d6f870003d15 [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 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000205 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000206 {
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
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000215 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000216 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
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000329 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000330 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000331 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000332 if UnalignedAllowed then
333 LoadWritePC(MemU[address,4]);
334 else
335 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000336 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
337 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000338 }
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
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000386 // 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();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000457 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000458 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) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000684 case eEncodingT1:
685 Rd = Bits32(opcode, 10, 8);
686 setflags = !InITBlock();
687 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
688 carry = APSR_C;
689
690 break;
691
692 case eEncodingT2:
693 Rd = Bits32(opcode, 11, 8);
694 setflags = BitIsSet(opcode, 20);
695 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
696 if (BadReg(Rd))
697 return false;
698
699 break;
700
701 case eEncodingT3:
702 {
703 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
704 Rd = Bits32 (opcode, 11, 8);
705 setflags = false;
706 uint32_t imm4 = Bits32 (opcode, 19, 16);
707 uint32_t imm3 = Bits32 (opcode, 14, 12);
708 uint32_t i = Bit32 (opcode, 26);
709 uint32_t imm8 = Bits32 (opcode, 7, 0);
710 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
711
712 // if BadReg(d) then UNPREDICTABLE;
713 if (BadReg (Rd))
714 return false;
715 }
716 break;
717
718 case eEncodingA1:
719 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
720 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
721 Rd = Bits32 (opcode, 15, 12);
722 setflags = BitIsSet (opcode, 20);
723 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
724
725 break;
726
727 case eEncodingA2:
728 {
729 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
730 Rd = Bits32 (opcode, 15, 12);
731 setflags = false;
732 uint32_t imm4 = Bits32 (opcode, 19, 16);
733 uint32_t imm12 = Bits32 (opcode, 11, 0);
734 imm32 = (imm4 << 12) | imm12;
735
736 // if d == 15 then UNPREDICTABLE;
737 if (Rd == 15)
738 return false;
739 }
740 break;
741
742 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000743 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000744 }
745 uint32_t result = imm32;
746
747 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000748 EmulateInstruction::Context context;
749 context.type = EmulateInstruction::eContextImmediate;
750 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000751
Johnny Chen10530c22011-02-17 22:37:12 +0000752 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000753 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000754 }
755 return true;
756}
757
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000758// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
759// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
760// unsigned values.
761//
762// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
763// limited to only a few forms of the instruction.
764bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000765EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000766{
767#if 0
768 if ConditionPassed() then
769 EncodingSpecificOperations();
770 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
771 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
772 result = operand1 * operand2;
773 R[d] = result<31:0>;
774 if setflags then
775 APSR.N = result<31>;
776 APSR.Z = IsZeroBit(result);
777 if ArchVersion() == 4 then
778 APSR.C = bit UNKNOWN;
779 // else APSR.C unchanged
780 // APSR.V always unchanged
781#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000782
Greg Clayton7bc39082011-03-24 23:53:38 +0000783 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000784 {
785 uint32_t d;
786 uint32_t n;
787 uint32_t m;
788 bool setflags;
789
790 // EncodingSpecificOperations();
791 switch (encoding)
792 {
793 case eEncodingT1:
794 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
795 d = Bits32 (opcode, 2, 0);
796 n = Bits32 (opcode, 5, 3);
797 m = Bits32 (opcode, 2, 0);
798 setflags = !InITBlock();
799
800 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
801 if ((ArchVersion() < ARMv6) && (d == n))
802 return false;
803
804 break;
805
806 case eEncodingT2:
807 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
808 d = Bits32 (opcode, 11, 8);
809 n = Bits32 (opcode, 19, 16);
810 m = Bits32 (opcode, 3, 0);
811 setflags = false;
812
813 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
814 if (BadReg (d) || BadReg (n) || BadReg (m))
815 return false;
816
817 break;
818
819 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000820 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000821 d = Bits32 (opcode, 19, 16);
822 n = Bits32 (opcode, 3, 0);
823 m = Bits32 (opcode, 11, 8);
824 setflags = BitIsSet (opcode, 20);
825
826 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
827 if ((d == 15) || (n == 15) || (m == 15))
828 return false;
829
830 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
831 if ((ArchVersion() < ARMv6) && (d == n))
832 return false;
833
834 break;
835
836 default:
837 return false;
838 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000839
840 bool success = false;
841
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000842 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
843 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
844 if (!success)
845 return false;
846
847 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
848 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
849 if (!success)
850 return false;
851
852 // result = operand1 * operand2;
853 uint64_t result = operand1 * operand2;
854
855 // R[d] = result<31:0>;
856 Register op1_reg;
857 Register op2_reg;
858 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
859 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
860
861 EmulateInstruction::Context context;
862 context.type = eContextMultiplication;
863 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
864
865 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
866 return false;
867
868 // if setflags then
869 if (setflags)
870 {
871 // APSR.N = result<31>;
872 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000873 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000874 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
875 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000876 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000877 {
878 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
879 return false;
880 }
881
882 // if ArchVersion() == 4 then
883 // APSR.C = bit UNKNOWN;
884 }
885 }
886 return true;
887}
888
Johnny Chend642a6a2011-02-22 01:01:03 +0000889// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
890// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000891bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000892EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000893{
894#if 0
895 // ARM pseudo code...
896 if (ConditionPassed())
897 {
898 EncodingSpecificOperations();
899 result = NOT(imm32);
900 if d == 15 then // Can only occur for ARM encoding
901 ALUWritePC(result); // setflags is always FALSE here
902 else
903 R[d] = result;
904 if setflags then
905 APSR.N = result<31>;
906 APSR.Z = IsZeroBit(result);
907 APSR.C = carry;
908 // APSR.V unchanged
909 }
910#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000911
Greg Clayton7bc39082011-03-24 23:53:38 +0000912 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000913 {
914 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000915 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
916 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000917 bool setflags;
918 switch (encoding) {
919 case eEncodingT1:
920 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000921 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000922 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000923 break;
924 case eEncodingA1:
925 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000926 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000927 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
928 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
929 // TODO: Emulate SUBS PC, LR and related instructions.
930 if (Rd == 15 && setflags)
931 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000932 break;
933 default:
934 return false;
935 }
936 uint32_t result = ~imm32;
937
938 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000939 EmulateInstruction::Context context;
940 context.type = EmulateInstruction::eContextImmediate;
941 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000942
Johnny Chen10530c22011-02-17 22:37:12 +0000943 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000944 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000945 }
946 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000947}
948
Johnny Chend642a6a2011-02-22 01:01:03 +0000949// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
950// It can optionally update the condition flags based on the result.
951bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000952EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +0000953{
954#if 0
955 // ARM pseudo code...
956 if (ConditionPassed())
957 {
958 EncodingSpecificOperations();
959 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
960 result = NOT(shifted);
961 if d == 15 then // Can only occur for ARM encoding
962 ALUWritePC(result); // setflags is always FALSE here
963 else
964 R[d] = result;
965 if setflags then
966 APSR.N = result<31>;
967 APSR.Z = IsZeroBit(result);
968 APSR.C = carry;
969 // APSR.V unchanged
970 }
971#endif
972
Greg Clayton7bc39082011-03-24 23:53:38 +0000973 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +0000974 {
975 uint32_t Rm; // the source register
976 uint32_t Rd; // the destination register
977 ARM_ShifterType shift_t;
978 uint32_t shift_n; // the shift applied to the value read from Rm
979 bool setflags;
980 uint32_t carry; // the carry bit after the shift operation
981 switch (encoding) {
982 case eEncodingT1:
983 Rd = Bits32(opcode, 2, 0);
984 Rm = Bits32(opcode, 5, 3);
985 setflags = !InITBlock();
986 shift_t = SRType_LSL;
987 shift_n = 0;
988 if (InITBlock())
989 return false;
990 break;
991 case eEncodingT2:
992 Rd = Bits32(opcode, 11, 8);
993 Rm = Bits32(opcode, 3, 0);
994 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000995 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000996 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000997 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000998 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000999 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001000 case eEncodingA1:
1001 Rd = Bits32(opcode, 15, 12);
1002 Rm = Bits32(opcode, 3, 0);
1003 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001004 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001005 break;
1006 default:
1007 return false;
1008 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001009 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001010 uint32_t value = ReadCoreReg(Rm, &success);
1011 if (!success)
1012 return false;
1013
1014 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1015 uint32_t result = ~shifted;
1016
1017 // The context specifies that an immediate is to be moved into Rd.
1018 EmulateInstruction::Context context;
1019 context.type = EmulateInstruction::eContextImmediate;
1020 context.SetNoArgs ();
1021
1022 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1023 return false;
1024 }
1025 return true;
1026}
1027
Johnny Chen788e0552011-01-27 22:52:23 +00001028// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1029// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001030bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001031EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001032{
1033#if 0
1034 // ARM pseudo code...
1035 if (ConditionPassed())
1036 {
1037 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1038 base = Align(PC,4);
1039 address = if add then (base + imm32) else (base - imm32);
1040 data = MemU[address,4];
1041 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001042 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1043 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001044 R[t] = data;
1045 else // Can only apply before ARMv7
1046 if CurrentInstrSet() == InstrSet_ARM then
1047 R[t] = ROR(data, 8*UInt(address<1:0>));
1048 else
1049 R[t] = bits(32) UNKNOWN;
1050 }
1051#endif
1052
Greg Clayton7bc39082011-03-24 23:53:38 +00001053 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001054 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001055 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001056 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001057 if (!success)
1058 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001059
1060 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001061 EmulateInstruction::Context context;
1062 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1063 Register pc_reg;
1064 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1065 context.SetRegisterPlusOffset (pc_reg, 0);
1066
Johnny Chenc9de9102011-02-11 19:12:30 +00001067 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001068 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001069 bool add; // +imm32 or -imm32?
1070 addr_t base; // the base address
1071 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001072 uint32_t data; // the literal data value from the PC relative load
1073 switch (encoding) {
1074 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001075 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001076 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001077 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001078 break;
1079 case eEncodingT2:
1080 Rt = Bits32(opcode, 15, 12);
1081 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1082 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001083 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001084 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001085 break;
1086 default:
1087 return false;
1088 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001089
Johnny Chene39f22d2011-02-19 01:36:13 +00001090 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001091 if (add)
1092 address = base + imm32;
1093 else
1094 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001095
1096 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001097 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001098 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001099 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001100
1101 if (Rt == 15)
1102 {
1103 if (Bits32(address, 1, 0) == 0)
1104 {
1105 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001106 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001107 return false;
1108 }
1109 else
1110 return false;
1111 }
1112 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1113 {
1114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1115 return false;
1116 }
1117 else // We don't handle ARM for now.
1118 return false;
1119
Johnny Chen788e0552011-01-27 22:52:23 +00001120 }
1121 return true;
1122}
1123
Johnny Chen5b442b72011-01-27 19:34:30 +00001124// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001125// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001126bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001127EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001128{
1129#if 0
1130 // ARM pseudo code...
1131 if (ConditionPassed())
1132 {
1133 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001134 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001135 if d == 15 then // Can only occur for ARM encoding
1136 ALUWritePC(result); // setflags is always FALSE here
1137 else
1138 R[d] = result;
1139 if setflags then
1140 APSR.N = result<31>;
1141 APSR.Z = IsZeroBit(result);
1142 APSR.C = carry;
1143 APSR.V = overflow;
1144 }
1145#endif
1146
1147 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001148
Greg Clayton7bc39082011-03-24 23:53:38 +00001149 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001150 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001151 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001152 if (!success)
1153 return false;
1154 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001155 uint32_t d;
1156 bool setflags;
1157 switch (encoding)
1158 {
1159 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001160 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001161 d = Bits32 (opcode, 10, 8);
1162 setflags = false;
1163 imm32 = (Bits32 (opcode, 7, 0) << 2);
1164
1165 break;
1166
1167 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001168 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001169 d = 13;
1170 setflags = false;
1171 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1172
1173 break;
1174
1175 default:
1176 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001177 }
1178 addr_t sp_offset = imm32;
1179 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1180
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001181 EmulateInstruction::Context context;
1182 context.type = EmulateInstruction::eContextAdjustStackPointer;
1183 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001184
Caroline Ticee2212882011-03-22 22:38:28 +00001185 if (d == 15)
1186 {
1187 if (!ALUWritePC (context, addr))
1188 return false;
1189 }
1190 else
1191 {
1192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1193 return false;
1194 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001195 }
1196 return true;
1197}
1198
1199// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001200// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001201bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001202EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001203{
1204#if 0
1205 // ARM pseudo code...
1206 if (ConditionPassed())
1207 {
1208 EncodingSpecificOperations();
1209 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001210 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001211 if d == 15 then
1212 ALUWritePC(result); // setflags is always FALSE here
1213 else
1214 R[d] = result;
1215 if setflags then
1216 APSR.N = result<31>;
1217 APSR.Z = IsZeroBit(result);
1218 APSR.C = carry;
1219 APSR.V = overflow;
1220 }
1221#endif
1222
1223 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001224
Greg Clayton7bc39082011-03-24 23:53:38 +00001225 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001226 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001227 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001228 if (!success)
1229 return false;
1230 uint32_t Rm; // the second operand
1231 switch (encoding) {
1232 case eEncodingT2:
1233 Rm = Bits32(opcode, 6, 3);
1234 break;
1235 default:
1236 return false;
1237 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001238 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001239 if (!success)
1240 return false;
1241
1242 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1243
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001244 EmulateInstruction::Context context;
1245 context.type = EmulateInstruction::eContextAdjustStackPointer;
1246 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001247
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001248 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001249 return false;
1250 }
1251 return true;
1252}
1253
Johnny Chen9b8d7832011-02-02 01:13:56 +00001254// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1255// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1256// from Thumb to ARM.
1257// BLX (immediate)
1258bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001259EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001260{
1261#if 0
1262 // ARM pseudo code...
1263 if (ConditionPassed())
1264 {
1265 EncodingSpecificOperations();
1266 if CurrentInstrSet() == InstrSet_ARM then
1267 LR = PC - 4;
1268 else
1269 LR = PC<31:1> : '1';
1270 if targetInstrSet == InstrSet_ARM then
1271 targetAddress = Align(PC,4) + imm32;
1272 else
1273 targetAddress = PC + imm32;
1274 SelectInstrSet(targetInstrSet);
1275 BranchWritePC(targetAddress);
1276 }
1277#endif
1278
Greg Clayton7bc39082011-03-24 23:53:38 +00001279 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001280
Greg Clayton7bc39082011-03-24 23:53:38 +00001281 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001282 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001283 EmulateInstruction::Context context;
1284 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001285 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001286 if (!success)
1287 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001288 addr_t lr; // next instruction address
1289 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001290 int32_t imm32; // PC-relative offset
1291 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001292 case eEncodingT1:
1293 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001294 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001295 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001296 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001297 uint32_t J1 = Bit32(opcode, 13);
1298 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001299 uint32_t imm11 = Bits32(opcode, 10, 0);
1300 uint32_t I1 = !(J1 ^ S);
1301 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001302 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001303 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001304 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001305 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001306 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001307 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001308 break;
1309 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001310 case eEncodingT2:
1311 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001312 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001313 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001314 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001315 uint32_t J1 = Bit32(opcode, 13);
1316 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001317 uint32_t imm10L = Bits32(opcode, 10, 1);
1318 uint32_t I1 = !(J1 ^ S);
1319 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001320 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001321 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001322 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001323 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001324 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001325 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001326 break;
1327 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001328 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001329 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001330 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001331 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001332 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001333 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001334 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001335 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001336 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001337 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001338 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001339 break;
1340 default:
1341 return false;
1342 }
1343 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1344 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001345 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001346 return false;
1347 }
1348 return true;
1349}
1350
1351// Branch with Link and Exchange (register) calls a subroutine at an address and
1352// instruction set specified by a register.
1353// BLX (register)
1354bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001355EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356{
1357#if 0
1358 // ARM pseudo code...
1359 if (ConditionPassed())
1360 {
1361 EncodingSpecificOperations();
1362 target = R[m];
1363 if CurrentInstrSet() == InstrSet_ARM then
1364 next_instr_addr = PC - 4;
1365 LR = next_instr_addr;
1366 else
1367 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001368 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001369 BXWritePC(target);
1370 }
1371#endif
1372
1373 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001374
Greg Clayton7bc39082011-03-24 23:53:38 +00001375 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001377 EmulateInstruction::Context context;
1378 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001380 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 if (!success)
1382 return false;
1383 uint32_t Rm; // the register with the target address
1384 switch (encoding) {
1385 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001386 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001387 Rm = Bits32(opcode, 6, 3);
1388 // if m == 15 then UNPREDICTABLE;
1389 if (Rm == 15)
1390 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001391 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001392 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001393 break;
1394 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001395 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001396 Rm = Bits32(opcode, 3, 0);
1397 // if m == 15 then UNPREDICTABLE;
1398 if (Rm == 15)
1399 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001400 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001401 default:
1402 return false;
1403 }
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 Register dwarf_reg;
1408 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1409 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001410 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1411 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001412 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001413 return false;
1414 }
1415 return true;
1416}
1417
Johnny Chenab3b3512011-02-12 00:10:51 +00001418// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001419bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001420EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001421{
1422#if 0
1423 // ARM pseudo code...
1424 if (ConditionPassed())
1425 {
1426 EncodingSpecificOperations();
1427 BXWritePC(R[m]);
1428 }
1429#endif
1430
Greg Clayton7bc39082011-03-24 23:53:38 +00001431 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001432 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001433 EmulateInstruction::Context context;
1434 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001435 uint32_t Rm; // the register with the target address
1436 switch (encoding) {
1437 case eEncodingT1:
1438 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001439 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001440 return false;
1441 break;
1442 case eEncodingA1:
1443 Rm = Bits32(opcode, 3, 0);
1444 break;
1445 default:
1446 return false;
1447 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001448 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001449 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001450 if (!success)
1451 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001452
1453 Register dwarf_reg;
1454 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001455 context.SetRegister (dwarf_reg);
1456 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001457 return false;
1458 }
1459 return true;
1460}
1461
Johnny Chen59e6ab72011-02-24 21:01:20 +00001462// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1463// address and instruction set specified by a register as though it were a BX instruction.
1464//
1465// TODO: Emulate Jazelle architecture?
1466// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1467bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001468EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001469{
1470#if 0
1471 // ARM pseudo code...
1472 if (ConditionPassed())
1473 {
1474 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001475 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001476 BXWritePC(R[m]);
1477 else
1478 if JazelleAcceptsExecution() then
1479 SwitchToJazelleExecution();
1480 else
1481 SUBARCHITECTURE_DEFINED handler call;
1482 }
1483#endif
1484
Greg Clayton7bc39082011-03-24 23:53:38 +00001485 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001486 {
1487 EmulateInstruction::Context context;
1488 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1489 uint32_t Rm; // the register with the target address
1490 switch (encoding) {
1491 case eEncodingT1:
1492 Rm = Bits32(opcode, 19, 16);
1493 if (BadReg(Rm))
1494 return false;
1495 if (InITBlock() && !LastInITBlock())
1496 return false;
1497 break;
1498 case eEncodingA1:
1499 Rm = Bits32(opcode, 3, 0);
1500 if (Rm == 15)
1501 return false;
1502 break;
1503 default:
1504 return false;
1505 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001506 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001507 addr_t target = ReadCoreReg (Rm, &success);
1508 if (!success)
1509 return false;
1510
1511 Register dwarf_reg;
1512 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1513 context.SetRegister (dwarf_reg);
1514 if (!BXWritePC(context, target))
1515 return false;
1516 }
1517 return true;
1518}
1519
Johnny Chen0d0148e2011-01-28 02:26:08 +00001520// Set r7 to point to some ip offset.
1521// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001522bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001523EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001524{
1525#if 0
1526 // ARM pseudo code...
1527 if (ConditionPassed())
1528 {
1529 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001530 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001531 if d == 15 then // Can only occur for ARM encoding
1532 ALUWritePC(result); // setflags is always FALSE here
1533 else
1534 R[d] = result;
1535 if setflags then
1536 APSR.N = result<31>;
1537 APSR.Z = IsZeroBit(result);
1538 APSR.C = carry;
1539 APSR.V = overflow;
1540 }
1541#endif
1542
Greg Clayton7bc39082011-03-24 23:53:38 +00001543 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001544 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001545 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001546 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001547 if (!success)
1548 return false;
1549 uint32_t imm32;
1550 switch (encoding) {
1551 case eEncodingA1:
1552 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1553 break;
1554 default:
1555 return false;
1556 }
1557 addr_t ip_offset = imm32;
1558 addr_t addr = ip - ip_offset; // the adjusted ip value
1559
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001560 EmulateInstruction::Context context;
1561 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1562 Register dwarf_reg;
1563 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1564 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001565
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001567 return false;
1568 }
1569 return true;
1570}
1571
1572// Set ip to point to some stack offset.
1573// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001574bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001575EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001576{
1577#if 0
1578 // ARM pseudo code...
1579 if (ConditionPassed())
1580 {
1581 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001582 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001583 if d == 15 then // Can only occur for ARM encoding
1584 ALUWritePC(result); // setflags is always FALSE here
1585 else
1586 R[d] = result;
1587 if setflags then
1588 APSR.N = result<31>;
1589 APSR.Z = IsZeroBit(result);
1590 APSR.C = carry;
1591 APSR.V = overflow;
1592 }
1593#endif
1594
Greg Clayton7bc39082011-03-24 23:53:38 +00001595 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001596 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001597 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001598 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001599 if (!success)
1600 return false;
1601 uint32_t imm32;
1602 switch (encoding) {
1603 case eEncodingA1:
1604 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1605 break;
1606 default:
1607 return false;
1608 }
1609 addr_t sp_offset = imm32;
1610 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1611
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001612 EmulateInstruction::Context context;
1613 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1614 Register dwarf_reg;
1615 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1616 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001617
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001619 return false;
1620 }
1621 return true;
1622}
1623
Johnny Chenc9e747f2011-02-23 01:55:07 +00001624// This instruction subtracts an immediate value from the SP value, and writes
1625// the result to the destination register.
1626//
1627// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001628bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001629EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001630{
1631#if 0
1632 // ARM pseudo code...
1633 if (ConditionPassed())
1634 {
1635 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001636 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001637 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001638 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001639 else
1640 R[d] = result;
1641 if setflags then
1642 APSR.N = result<31>;
1643 APSR.Z = IsZeroBit(result);
1644 APSR.C = carry;
1645 APSR.V = overflow;
1646 }
1647#endif
1648
1649 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001650 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001651 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001652 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001653 if (!success)
1654 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001655
1656 uint32_t Rd;
1657 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001658 uint32_t imm32;
1659 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001660 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001661 Rd = 13;
1662 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001663 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001664 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001665 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001666 Rd = Bits32(opcode, 11, 8);
1667 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001668 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001669 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001670 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001671 if (Rd == 15 && !setflags)
1672 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001673 break;
1674 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001675 Rd = Bits32(opcode, 11, 8);
1676 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001677 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001678 if (Rd == 15)
1679 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001680 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001681 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001682 Rd = Bits32(opcode, 15, 12);
1683 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001684 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001685 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1686 // TODO: Emulate SUBS PC, LR and related instructions.
1687 if (Rd == 15 && setflags)
1688 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001689 break;
1690 default:
1691 return false;
1692 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001693 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1694
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001695 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001696 if (Rd == 13)
1697 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001698 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1699 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001700 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001701 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001702 }
1703 else
1704 {
1705 context.type = EmulateInstruction::eContextImmediate;
1706 context.SetNoArgs ();
1707 }
1708
1709 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001710 return false;
1711 }
1712 return true;
1713}
1714
Johnny Chen08c25e82011-01-31 18:02:28 +00001715// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001716bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001717EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001718{
1719#if 0
1720 // ARM pseudo code...
1721 if (ConditionPassed())
1722 {
1723 EncodingSpecificOperations();
1724 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1725 address = if index then offset_addr else R[n];
1726 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1727 if wback then R[n] = offset_addr;
1728 }
1729#endif
1730
1731 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001732
Greg Clayton7bc39082011-03-24 23:53:38 +00001733 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001734 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001735 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001736 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001737 if (!success)
1738 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001739 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001740 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001741 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1742
1743 bool index;
1744 bool add;
1745 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001746 switch (encoding) {
1747 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001748 Rt = Bits32(opcode, 15, 12);
1749 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001750 Rn = Bits32 (opcode, 19, 16);
1751
1752 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1753 return false;
1754
1755 index = BitIsSet (opcode, 24);
1756 add = BitIsSet (opcode, 23);
1757 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1758
1759 if (wback && ((Rn == 15) || (Rn == Rt)))
1760 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001761 break;
1762 default:
1763 return false;
1764 }
Caroline Tice3e407972011-03-18 19:41:00 +00001765 addr_t offset_addr;
1766 if (add)
1767 offset_addr = sp + imm12;
1768 else
1769 offset_addr = sp - imm12;
1770
1771 addr_t addr;
1772 if (index)
1773 addr = offset_addr;
1774 else
1775 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001776
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001777 EmulateInstruction::Context context;
1778 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001779 Register sp_reg;
1780 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1781 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001782 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001783 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001784 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001785 if (!success)
1786 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001787 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001788 return false;
1789 }
1790 else
1791 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001792 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001793 if (!success)
1794 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001795 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001796 return false;
1797 }
1798
Caroline Tice3e407972011-03-18 19:41:00 +00001799
1800 if (wback)
1801 {
1802 context.type = EmulateInstruction::eContextAdjustStackPointer;
1803 context.SetImmediateSigned (addr - sp);
1804 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1805 return false;
1806 }
Johnny Chence1ca772011-01-25 01:13:00 +00001807 }
1808 return true;
1809}
1810
Johnny Chen08c25e82011-01-31 18:02:28 +00001811// Vector Push stores multiple extension registers to the stack.
1812// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001813bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001814EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001815{
1816#if 0
1817 // ARM pseudo code...
1818 if (ConditionPassed())
1819 {
1820 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1821 address = SP - imm32;
1822 SP = SP - imm32;
1823 if single_regs then
1824 for r = 0 to regs-1
1825 MemA[address,4] = S[d+r]; address = address+4;
1826 else
1827 for r = 0 to regs-1
1828 // Store as two word-aligned words in the correct order for current endianness.
1829 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1830 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1831 address = address+8;
1832 }
1833#endif
1834
1835 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001836
Greg Clayton7bc39082011-03-24 23:53:38 +00001837 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001838 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001839 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001840 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001841 if (!success)
1842 return false;
1843 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001844 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001845 uint32_t imm32; // stack offset
1846 uint32_t regs; // number of registers
1847 switch (encoding) {
1848 case eEncodingT1:
1849 case eEncodingA1:
1850 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001851 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001852 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1853 // If UInt(imm8) is odd, see "FSTMX".
1854 regs = Bits32(opcode, 7, 0) / 2;
1855 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1856 if (regs == 0 || regs > 16 || (d + regs) > 32)
1857 return false;
1858 break;
1859 case eEncodingT2:
1860 case eEncodingA2:
1861 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001862 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001863 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1864 regs = Bits32(opcode, 7, 0);
1865 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1866 if (regs == 0 || regs > 16 || (d + regs) > 32)
1867 return false;
1868 break;
1869 default:
1870 return false;
1871 }
1872 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1873 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1874 addr_t sp_offset = imm32;
1875 addr_t addr = sp - sp_offset;
1876 uint32_t i;
1877
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001878 EmulateInstruction::Context context;
1879 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1880 Register dwarf_reg;
1881 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001882 Register sp_reg;
1883 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1884 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001885 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001886 dwarf_reg.num = start_reg + d + i;
1887 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001888 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001889 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001890 if (!success)
1891 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001892 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001893 return false;
1894 addr += reg_byte_size;
1895 }
1896
1897 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001898 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001899
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001900 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001901 return false;
1902 }
1903 return true;
1904}
1905
Johnny Chen587a0a42011-02-01 18:35:28 +00001906// Vector Pop loads multiple extension registers from the stack.
1907// It also updates SP to point just above the loaded data.
1908bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001909EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001910{
1911#if 0
1912 // ARM pseudo code...
1913 if (ConditionPassed())
1914 {
1915 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1916 address = SP;
1917 SP = SP + imm32;
1918 if single_regs then
1919 for r = 0 to regs-1
1920 S[d+r] = MemA[address,4]; address = address+4;
1921 else
1922 for r = 0 to regs-1
1923 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1924 // Combine the word-aligned words in the correct order for current endianness.
1925 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1926 }
1927#endif
1928
1929 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001930
Greg Clayton7bc39082011-03-24 23:53:38 +00001931 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001932 {
1933 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001934 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001935 if (!success)
1936 return false;
1937 bool single_regs;
1938 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1939 uint32_t imm32; // stack offset
1940 uint32_t regs; // number of registers
1941 switch (encoding) {
1942 case eEncodingT1:
1943 case eEncodingA1:
1944 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001945 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001946 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1947 // If UInt(imm8) is odd, see "FLDMX".
1948 regs = Bits32(opcode, 7, 0) / 2;
1949 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1950 if (regs == 0 || regs > 16 || (d + regs) > 32)
1951 return false;
1952 break;
1953 case eEncodingT2:
1954 case eEncodingA2:
1955 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001956 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001957 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1958 regs = Bits32(opcode, 7, 0);
1959 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1960 if (regs == 0 || regs > 16 || (d + regs) > 32)
1961 return false;
1962 break;
1963 default:
1964 return false;
1965 }
1966 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1967 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1968 addr_t sp_offset = imm32;
1969 addr_t addr = sp;
1970 uint32_t i;
1971 uint64_t data; // uint64_t to accomodate 64-bit registers.
1972
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001973 EmulateInstruction::Context context;
1974 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1975 Register dwarf_reg;
1976 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001977 Register sp_reg;
1978 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1979 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00001980 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001981 dwarf_reg.num = start_reg + d + i;
1982 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001983 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001984 if (!success)
1985 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001986 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001987 return false;
1988 addr += reg_byte_size;
1989 }
1990
1991 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001992 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001993
1994 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1995 return false;
1996 }
1997 return true;
1998}
1999
Johnny Chenb77be412011-02-04 00:40:18 +00002000// SVC (previously SWI)
2001bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002002EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002003{
2004#if 0
2005 // ARM pseudo code...
2006 if (ConditionPassed())
2007 {
2008 EncodingSpecificOperations();
2009 CallSupervisor();
2010 }
2011#endif
2012
2013 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002014
Greg Clayton7bc39082011-03-24 23:53:38 +00002015 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002016 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002017 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002018 addr_t lr; // next instruction address
2019 if (!success)
2020 return false;
2021 uint32_t imm32; // the immediate constant
2022 uint32_t mode; // ARM or Thumb mode
2023 switch (encoding) {
2024 case eEncodingT1:
2025 lr = (pc + 2) | 1u; // return address
2026 imm32 = Bits32(opcode, 7, 0);
2027 mode = eModeThumb;
2028 break;
2029 case eEncodingA1:
2030 lr = pc + 4; // return address
2031 imm32 = Bits32(opcode, 23, 0);
2032 mode = eModeARM;
2033 break;
2034 default:
2035 return false;
2036 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002037
2038 EmulateInstruction::Context context;
2039 context.type = EmulateInstruction::eContextSupervisorCall;
2040 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002041 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2042 return false;
2043 }
2044 return true;
2045}
2046
Johnny Chenc315f862011-02-05 00:46:10 +00002047// If Then makes up to four following instructions (the IT block) conditional.
2048bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002049EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002050{
2051#if 0
2052 // ARM pseudo code...
2053 EncodingSpecificOperations();
2054 ITSTATE.IT<7:0> = firstcond:mask;
2055#endif
2056
Johnny Chenc315f862011-02-05 00:46:10 +00002057 m_it_session.InitIT(Bits32(opcode, 7, 0));
2058 return true;
2059}
2060
Johnny Chen3b620b32011-02-07 20:11:47 +00002061// Branch causes a branch to a target address.
2062bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002063EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002064{
2065#if 0
2066 // ARM pseudo code...
2067 if (ConditionPassed())
2068 {
2069 EncodingSpecificOperations();
2070 BranchWritePC(PC + imm32);
2071 }
2072#endif
2073
2074 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002075
Greg Clayton7bc39082011-03-24 23:53:38 +00002076 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002077 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002078 EmulateInstruction::Context context;
2079 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002080 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002081 if (!success)
2082 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002083 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002084 int32_t imm32; // PC-relative offset
2085 switch (encoding) {
2086 case eEncodingT1:
2087 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2088 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002089 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002090 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002091 break;
2092 case eEncodingT2:
2093 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002094 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002095 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002096 break;
2097 case eEncodingT3:
2098 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2099 {
Johnny Chenbd599902011-02-10 21:39:01 +00002100 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002101 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002102 uint32_t J1 = Bit32(opcode, 13);
2103 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002104 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002105 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002106 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002107 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002108 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002109 break;
2110 }
2111 case eEncodingT4:
2112 {
Johnny Chenbd599902011-02-10 21:39:01 +00002113 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002114 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002115 uint32_t J1 = Bit32(opcode, 13);
2116 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002117 uint32_t imm11 = Bits32(opcode, 10, 0);
2118 uint32_t I1 = !(J1 ^ S);
2119 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002120 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002121 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002122 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002123 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002124 break;
2125 }
2126 case eEncodingA1:
2127 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002128 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002129 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002130 break;
2131 default:
2132 return false;
2133 }
2134 if (!BranchWritePC(context, target))
2135 return false;
2136 }
2137 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002138}
2139
Johnny Chen53ebab72011-02-08 23:21:57 +00002140// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2141// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2142// CBNZ, CBZ
2143bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002144EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002145{
2146#if 0
2147 // ARM pseudo code...
2148 EncodingSpecificOperations();
2149 if nonzero ^ IsZero(R[n]) then
2150 BranchWritePC(PC + imm32);
2151#endif
2152
2153 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002154
2155 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002156 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002157 if (!success)
2158 return false;
2159
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002160 EmulateInstruction::Context context;
2161 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002162 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002163 if (!success)
2164 return false;
2165
2166 addr_t target; // target address
2167 uint32_t imm32; // PC-relative offset to branch forward
2168 bool nonzero;
2169 switch (encoding) {
2170 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002171 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002172 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002173 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002174 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002175 break;
2176 default:
2177 return false;
2178 }
2179 if (nonzero ^ (reg_val == 0))
2180 if (!BranchWritePC(context, target))
2181 return false;
2182
2183 return true;
2184}
2185
Johnny Chen60299ec2011-02-17 19:34:27 +00002186// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2187// A base register provides a pointer to the table, and a second register supplies an index into the table.
2188// The branch length is twice the value of the byte returned from the table.
2189//
2190// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2191// A base register provides a pointer to the table, and a second register supplies an index into the table.
2192// The branch length is twice the value of the halfword returned from the table.
2193// TBB, TBH
2194bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002195EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002196{
2197#if 0
2198 // ARM pseudo code...
2199 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2200 if is_tbh then
2201 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2202 else
2203 halfwords = UInt(MemU[R[n]+R[m], 1]);
2204 BranchWritePC(PC + 2*halfwords);
2205#endif
2206
2207 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002208
2209 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2210 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2211 bool is_tbh; // true if table branch halfword
2212 switch (encoding) {
2213 case eEncodingT1:
2214 Rn = Bits32(opcode, 19, 16);
2215 Rm = Bits32(opcode, 3, 0);
2216 is_tbh = BitIsSet(opcode, 4);
2217 if (Rn == 13 || BadReg(Rm))
2218 return false;
2219 if (InITBlock() && !LastInITBlock())
2220 return false;
2221 break;
2222 default:
2223 return false;
2224 }
2225
2226 // Read the address of the table from the operand register Rn.
2227 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002228 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002229 if (!success)
2230 return false;
2231
2232 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002233 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002234 if (!success)
2235 return false;
2236
2237 // the offsetted table address
2238 addr_t addr = base + (is_tbh ? index*2 : index);
2239
2240 // PC-relative offset to branch forward
2241 EmulateInstruction::Context context;
2242 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002243 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002244 if (!success)
2245 return false;
2246
Johnny Chene39f22d2011-02-19 01:36:13 +00002247 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002248 if (!success)
2249 return false;
2250
2251 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002252 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002253 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2254 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2255
2256 if (!BranchWritePC(context, target))
2257 return false;
2258
2259 return true;
2260}
2261
Caroline Ticedcc11b32011-03-02 23:57:02 +00002262// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2263// It can optionally update the condition flags based on the result.
2264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002265EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002266{
2267#if 0
2268 if ConditionPassed() then
2269 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002270 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002271 R[d] = result;
2272 if setflags then
2273 APSR.N = result<31>;
2274 APSR.Z = IsZeroBit(result);
2275 APSR.C = carry;
2276 APSR.V = overflow;
2277#endif
2278
2279 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002280
Greg Clayton7bc39082011-03-24 23:53:38 +00002281 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002282 {
2283 uint32_t d;
2284 uint32_t n;
2285 bool setflags;
2286 uint32_t imm32;
2287 uint32_t carry_out;
2288
2289 //EncodingSpecificOperations();
2290 switch (encoding)
2291 {
2292 case eEncodingT1:
2293 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2294 d = Bits32 (opcode, 2, 0);
2295 n = Bits32 (opcode, 5, 3);
2296 setflags = !InITBlock();
2297 imm32 = Bits32 (opcode, 8,6);
2298
2299 break;
2300
2301 case eEncodingT2:
2302 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2303 d = Bits32 (opcode, 10, 8);
2304 n = Bits32 (opcode, 10, 8);
2305 setflags = !InITBlock();
2306 imm32 = Bits32 (opcode, 7, 0);
2307
2308 break;
2309
2310 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002311 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2312 // if Rn == '1101' then SEE ADD (SP plus immediate);
2313 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002314 d = Bits32 (opcode, 11, 8);
2315 n = Bits32 (opcode, 19, 16);
2316 setflags = BitIsSet (opcode, 20);
2317 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2318
2319 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2320 if (BadReg (d) || (n == 15))
2321 return false;
2322
2323 break;
2324
2325 case eEncodingT4:
2326 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002327 // if Rn == '1111' then SEE ADR;
2328 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002329 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2330 d = Bits32 (opcode, 11, 8);
2331 n = Bits32 (opcode, 19, 16);
2332 setflags = false;
2333 uint32_t i = Bit32 (opcode, 26);
2334 uint32_t imm3 = Bits32 (opcode, 14, 12);
2335 uint32_t imm8 = Bits32 (opcode, 7, 0);
2336 imm32 = (i << 11) | (imm3 << 8) | imm8;
2337
2338 // if BadReg(d) then UNPREDICTABLE;
2339 if (BadReg (d))
2340 return false;
2341
2342 break;
2343 }
2344 default:
2345 return false;
2346 }
2347
2348 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2349 if (!success)
2350 return false;
2351
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002352 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002353 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2354
2355 Register reg_n;
2356 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2357
2358 EmulateInstruction::Context context;
2359 context.type = eContextAddition;
2360 context.SetRegisterPlusOffset (reg_n, imm32);
2361
2362 //R[d] = result;
2363 //if setflags then
2364 //APSR.N = result<31>;
2365 //APSR.Z = IsZeroBit(result);
2366 //APSR.C = carry;
2367 //APSR.V = overflow;
2368 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2369 return false;
2370
2371 }
2372 return true;
2373}
2374
Johnny Chen8fa20592011-02-18 01:22:22 +00002375// This instruction adds an immediate value to a register value, and writes the result to the destination
2376// register. It can optionally update the condition flags based on the result.
2377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002378EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002379{
2380#if 0
2381 // ARM pseudo code...
2382 if ConditionPassed() then
2383 EncodingSpecificOperations();
2384 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2385 if d == 15 then
2386 ALUWritePC(result); // setflags is always FALSE here
2387 else
2388 R[d] = result;
2389 if setflags then
2390 APSR.N = result<31>;
2391 APSR.Z = IsZeroBit(result);
2392 APSR.C = carry;
2393 APSR.V = overflow;
2394#endif
2395
2396 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002397
Greg Clayton7bc39082011-03-24 23:53:38 +00002398 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002399 {
2400 uint32_t Rd, Rn;
2401 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2402 bool setflags;
2403 switch (encoding)
2404 {
2405 case eEncodingA1:
2406 Rd = Bits32(opcode, 15, 12);
2407 Rn = Bits32(opcode, 19, 16);
2408 setflags = BitIsSet(opcode, 20);
2409 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2410 break;
2411 default:
2412 return false;
2413 }
2414
Johnny Chen8fa20592011-02-18 01:22:22 +00002415 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002416 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002417 if (!success)
2418 return false;
2419
2420 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2421
2422 EmulateInstruction::Context context;
2423 context.type = EmulateInstruction::eContextImmediate;
2424 context.SetNoArgs ();
2425
2426 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2427 return false;
2428 }
2429 return true;
2430}
2431
Johnny Chend761dcf2011-02-17 22:03:29 +00002432// This instruction adds a register value and an optionally-shifted register value, and writes the result
2433// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002434bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002435EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002436{
2437#if 0
2438 // ARM pseudo code...
2439 if ConditionPassed() then
2440 EncodingSpecificOperations();
2441 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2442 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2443 if d == 15 then
2444 ALUWritePC(result); // setflags is always FALSE here
2445 else
2446 R[d] = result;
2447 if setflags then
2448 APSR.N = result<31>;
2449 APSR.Z = IsZeroBit(result);
2450 APSR.C = carry;
2451 APSR.V = overflow;
2452#endif
2453
2454 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002455
Greg Clayton7bc39082011-03-24 23:53:38 +00002456 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002457 {
2458 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002459 ARM_ShifterType shift_t;
2460 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002461 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002462 switch (encoding)
2463 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002464 case eEncodingT1:
2465 Rd = Bits32(opcode, 2, 0);
2466 Rn = Bits32(opcode, 5, 3);
2467 Rm = Bits32(opcode, 8, 6);
2468 setflags = !InITBlock();
2469 shift_t = SRType_LSL;
2470 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002471 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002472 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002473 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002474 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002475 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002476 shift_t = SRType_LSL;
2477 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002478 if (Rn == 15 && Rm == 15)
2479 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002480 if (Rd == 15 && InITBlock() && !LastInITBlock())
2481 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002482 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002483 case eEncodingA1:
2484 Rd = Bits32(opcode, 15, 12);
2485 Rn = Bits32(opcode, 19, 16);
2486 Rm = Bits32(opcode, 3, 0);
2487 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002488 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002489 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002490 default:
2491 return false;
2492 }
2493
Johnny Chen26863dc2011-02-09 23:43:29 +00002494 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002495 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002496 if (!success)
2497 return false;
2498
2499 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002500 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002501 if (!success)
2502 return false;
2503
Johnny Chene97c0d52011-02-18 19:32:20 +00002504 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002505 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002506
2507 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002508 context.type = EmulateInstruction::eContextAddition;
2509 Register op1_reg;
2510 Register op2_reg;
2511 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2512 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2513 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002514
Johnny Chen10530c22011-02-17 22:37:12 +00002515 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002516 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002517 }
2518 return true;
2519}
2520
Johnny Chen34075cb2011-02-22 01:56:31 +00002521// Compare Negative (immediate) adds a register value and an immediate value.
2522// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002523bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002524EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002525{
2526#if 0
2527 // ARM pseudo code...
2528 if ConditionPassed() then
2529 EncodingSpecificOperations();
2530 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2531 APSR.N = result<31>;
2532 APSR.Z = IsZeroBit(result);
2533 APSR.C = carry;
2534 APSR.V = overflow;
2535#endif
2536
2537 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002538
2539 uint32_t Rn; // the first operand
2540 uint32_t imm32; // the immediate value to be compared with
2541 switch (encoding) {
2542 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002543 Rn = Bits32(opcode, 19, 16);
2544 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2545 if (Rn == 15)
2546 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002547 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002548 case eEncodingA1:
2549 Rn = Bits32(opcode, 19, 16);
2550 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2551 break;
2552 default:
2553 return false;
2554 }
2555 // Read the register value from the operand register Rn.
2556 uint32_t reg_val = ReadCoreReg(Rn, &success);
2557 if (!success)
2558 return false;
2559
Johnny Chen078fbc62011-02-22 19:48:22 +00002560 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002561
2562 EmulateInstruction::Context context;
2563 context.type = EmulateInstruction::eContextImmediate;
2564 context.SetNoArgs ();
2565 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2566 return false;
2567
2568 return true;
2569}
2570
2571// Compare Negative (register) adds a register value and an optionally-shifted register value.
2572// It updates the condition flags based on the result, and discards the result.
2573bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002574EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002575{
2576#if 0
2577 // ARM pseudo code...
2578 if ConditionPassed() then
2579 EncodingSpecificOperations();
2580 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2581 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2582 APSR.N = result<31>;
2583 APSR.Z = IsZeroBit(result);
2584 APSR.C = carry;
2585 APSR.V = overflow;
2586#endif
2587
2588 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002589
2590 uint32_t Rn; // the first operand
2591 uint32_t Rm; // the second operand
2592 ARM_ShifterType shift_t;
2593 uint32_t shift_n; // the shift applied to the value read from Rm
2594 switch (encoding) {
2595 case eEncodingT1:
2596 Rn = Bits32(opcode, 2, 0);
2597 Rm = Bits32(opcode, 5, 3);
2598 shift_t = SRType_LSL;
2599 shift_n = 0;
2600 break;
2601 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002602 Rn = Bits32(opcode, 19, 16);
2603 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002604 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002605 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2606 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002607 return false;
2608 break;
2609 case eEncodingA1:
2610 Rn = Bits32(opcode, 19, 16);
2611 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002612 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002613 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002614 default:
2615 return false;
2616 }
2617 // Read the register value from register Rn.
2618 uint32_t val1 = ReadCoreReg(Rn, &success);
2619 if (!success)
2620 return false;
2621
2622 // Read the register value from register Rm.
2623 uint32_t val2 = ReadCoreReg(Rm, &success);
2624 if (!success)
2625 return false;
2626
2627 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002628 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002629
2630 EmulateInstruction::Context context;
2631 context.type = EmulateInstruction::eContextImmediate;
2632 context.SetNoArgs();
2633 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2634 return false;
2635
2636 return true;
2637}
2638
2639// Compare (immediate) subtracts an immediate value from a register value.
2640// It updates the condition flags based on the result, and discards the result.
2641bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002642EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002643{
2644#if 0
2645 // ARM pseudo code...
2646 if ConditionPassed() then
2647 EncodingSpecificOperations();
2648 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2649 APSR.N = result<31>;
2650 APSR.Z = IsZeroBit(result);
2651 APSR.C = carry;
2652 APSR.V = overflow;
2653#endif
2654
2655 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002656
2657 uint32_t Rn; // the first operand
2658 uint32_t imm32; // the immediate value to be compared with
2659 switch (encoding) {
2660 case eEncodingT1:
2661 Rn = Bits32(opcode, 10, 8);
2662 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002663 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002664 case eEncodingT2:
2665 Rn = Bits32(opcode, 19, 16);
2666 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2667 if (Rn == 15)
2668 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002669 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002670 case eEncodingA1:
2671 Rn = Bits32(opcode, 19, 16);
2672 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002673 break;
2674 default:
2675 return false;
2676 }
2677 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002678 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002679 if (!success)
2680 return false;
2681
Johnny Chen10530c22011-02-17 22:37:12 +00002682 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2683
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002684 EmulateInstruction::Context context;
2685 context.type = EmulateInstruction::eContextImmediate;
2686 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002687 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2688 return false;
2689
Johnny Chend4dc4442011-02-11 02:02:56 +00002690 return true;
2691}
2692
Johnny Chen34075cb2011-02-22 01:56:31 +00002693// Compare (register) subtracts an optionally-shifted register value from a register value.
2694// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002695bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002696EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002697{
2698#if 0
2699 // ARM pseudo code...
2700 if ConditionPassed() then
2701 EncodingSpecificOperations();
2702 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2703 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2704 APSR.N = result<31>;
2705 APSR.Z = IsZeroBit(result);
2706 APSR.C = carry;
2707 APSR.V = overflow;
2708#endif
2709
2710 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002711
2712 uint32_t Rn; // the first operand
2713 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002714 ARM_ShifterType shift_t;
2715 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002716 switch (encoding) {
2717 case eEncodingT1:
2718 Rn = Bits32(opcode, 2, 0);
2719 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002720 shift_t = SRType_LSL;
2721 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002722 break;
2723 case eEncodingT2:
2724 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2725 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002726 shift_t = SRType_LSL;
2727 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002728 if (Rn < 8 && Rm < 8)
2729 return false;
2730 if (Rn == 15 || Rm == 15)
2731 return false;
2732 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002733 case eEncodingA1:
2734 Rn = Bits32(opcode, 19, 16);
2735 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002736 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002737 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002738 default:
2739 return false;
2740 }
2741 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002742 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002743 if (!success)
2744 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002745
Johnny Chene4a4d302011-02-11 21:53:58 +00002746 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002747 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002748 if (!success)
2749 return false;
2750
Johnny Chen34075cb2011-02-22 01:56:31 +00002751 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2752 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002753
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002754 EmulateInstruction::Context context;
2755 context.type = EmulateInstruction::eContextImmediate;
2756 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002757 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2758 return false;
2759
Johnny Chene4a4d302011-02-11 21:53:58 +00002760 return true;
2761}
2762
Johnny Chen82f16aa2011-02-15 20:10:55 +00002763// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2764// shifting in copies of its sign bit, and writes the result to the destination register. It can
2765// optionally update the condition flags based on the result.
2766bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002767EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002768{
2769#if 0
2770 // ARM pseudo code...
2771 if ConditionPassed() then
2772 EncodingSpecificOperations();
2773 (result, carry) = Shift_C(R[m], SRType_ASR, 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_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002786}
2787
2788// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2789// shifting in copies of its sign bit, and writes the result to the destination register.
2790// The variable number of bits is read from the bottom byte of a register. It can optionally update
2791// the condition flags based on the result.
2792bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002793EmulateInstructionARM::EmulateASRReg (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_ASR, 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_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002810}
2811
2812// Logical Shift Left (immediate) shifts a register value left 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::EmulateLSLImm (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_LSL, 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_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002835}
2836
2837// Logical Shift Left (register) shifts a register value left 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::EmulateLSLReg (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_LSL, 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_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002859}
2860
2861// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2862// shifting in zeros, and writes the result to the destination register. It can optionally
2863// update the condition flags based on the result.
2864bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002865EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002866{
2867#if 0
2868 // ARM pseudo code...
2869 if ConditionPassed() then
2870 EncodingSpecificOperations();
2871 (result, carry) = Shift_C(R[m], SRType_LSR, 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_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002884}
2885
2886// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2887// shifting in zeros, and writes the result to the destination register. The variable number
2888// 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::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +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_LSR, 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_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002908}
2909
Johnny Cheneeab4852011-02-16 22:14:44 +00002910// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2911// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2912// It can optionally update the condition flags based on the result.
2913bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002914EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002915{
2916#if 0
2917 // ARM pseudo code...
2918 if ConditionPassed() then
2919 EncodingSpecificOperations();
2920 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2921 if d == 15 then // Can only occur for ARM encoding
2922 ALUWritePC(result); // setflags is always FALSE here
2923 else
2924 R[d] = result;
2925 if setflags then
2926 APSR.N = result<31>;
2927 APSR.Z = IsZeroBit(result);
2928 APSR.C = carry;
2929 // APSR.V unchanged
2930#endif
2931
Greg Clayton7bc39082011-03-24 23:53:38 +00002932 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002933}
2934
2935// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2936// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2937// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2938// flags based on the result.
2939bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002940EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002941{
2942#if 0
2943 // ARM pseudo code...
2944 if ConditionPassed() then
2945 EncodingSpecificOperations();
2946 shift_n = UInt(R[m]<7:0>);
2947 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2948 R[d] = result;
2949 if setflags then
2950 APSR.N = result<31>;
2951 APSR.Z = IsZeroBit(result);
2952 APSR.C = carry;
2953 // APSR.V unchanged
2954#endif
2955
Greg Clayton7bc39082011-03-24 23:53:38 +00002956 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002957}
2958
2959// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2960// with the carry flag shifted into bit [31].
2961//
2962// RRX can optionally update the condition flags based on the result.
2963// In that case, bit [0] is shifted into the carry flag.
2964bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002965EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002966{
2967#if 0
2968 // ARM pseudo code...
2969 if ConditionPassed() then
2970 EncodingSpecificOperations();
2971 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2972 if d == 15 then // Can only occur for ARM encoding
2973 ALUWritePC(result); // setflags is always FALSE here
2974 else
2975 R[d] = result;
2976 if setflags then
2977 APSR.N = result<31>;
2978 APSR.Z = IsZeroBit(result);
2979 APSR.C = carry;
2980 // APSR.V unchanged
2981#endif
2982
Greg Clayton7bc39082011-03-24 23:53:38 +00002983 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00002984}
2985
Johnny Chen41a0a152011-02-16 01:27:54 +00002986bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002987EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00002988{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002989 assert(shift_type == SRType_ASR
2990 || shift_type == SRType_LSL
2991 || shift_type == SRType_LSR
2992 || shift_type == SRType_ROR
2993 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00002994
Johnny Chen82f16aa2011-02-15 20:10:55 +00002995 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002996
Greg Clayton7bc39082011-03-24 23:53:38 +00002997 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002998 {
Johnny Chene7f89532011-02-15 23:22:46 +00002999 uint32_t Rd; // the destination register
3000 uint32_t Rm; // the first operand register
3001 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003002 uint32_t carry; // the carry bit after the shift operation
3003 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003004
3005 // Special case handling!
3006 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003007 ARMEncoding use_encoding = encoding;
3008 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003009 {
3010 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3011 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003012 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003013 }
3014
Greg Clayton7bc39082011-03-24 23:53:38 +00003015 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003016 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003017 // Due to the above special case handling!
3018 assert(shift_type != SRType_ROR);
3019
Johnny Chen82f16aa2011-02-15 20:10:55 +00003020 Rd = Bits32(opcode, 2, 0);
3021 Rm = Bits32(opcode, 5, 3);
3022 setflags = !InITBlock();
3023 imm5 = Bits32(opcode, 10, 6);
3024 break;
3025 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003026 // A8.6.141 RRX
3027 assert(shift_type != SRType_RRX);
3028
Johnny Chen82f16aa2011-02-15 20:10:55 +00003029 Rd = Bits32(opcode, 11, 8);
3030 Rm = Bits32(opcode, 3, 0);
3031 setflags = BitIsSet(opcode, 20);
3032 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3033 if (BadReg(Rd) || BadReg(Rm))
3034 return false;
3035 break;
3036 case eEncodingA1:
3037 Rd = Bits32(opcode, 15, 12);
3038 Rm = Bits32(opcode, 3, 0);
3039 setflags = BitIsSet(opcode, 20);
3040 imm5 = Bits32(opcode, 11, 7);
3041 break;
3042 default:
3043 return false;
3044 }
3045
Johnny Cheneeab4852011-02-16 22:14:44 +00003046 // A8.6.139 ROR (immediate)
3047 if (shift_type == SRType_ROR && imm5 == 0)
3048 shift_type = SRType_RRX;
3049
Johnny Chen82f16aa2011-02-15 20:10:55 +00003050 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003051 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003052 if (!success)
3053 return false;
3054
Johnny Cheneeab4852011-02-16 22:14:44 +00003055 // Decode the shift amount if not RRX.
3056 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003057
Johnny Chene97c0d52011-02-18 19:32:20 +00003058 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003059
3060 // The context specifies that an immediate is to be moved into Rd.
3061 EmulateInstruction::Context context;
3062 context.type = EmulateInstruction::eContextImmediate;
3063 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003064
Johnny Chen10530c22011-02-17 22:37:12 +00003065 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003066 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003067 }
3068 return true;
3069}
3070
Johnny Chene7f89532011-02-15 23:22:46 +00003071bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003072EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003073{
Johnny Chen41a0a152011-02-16 01:27:54 +00003074 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003075
3076 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003077
Greg Clayton7bc39082011-03-24 23:53:38 +00003078 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003079 {
3080 uint32_t Rd; // the destination register
3081 uint32_t Rn; // the first operand register
3082 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3083 uint32_t carry; // the carry bit after the shift operation
3084 bool setflags;
3085 switch (encoding) {
3086 case eEncodingT1:
3087 Rd = Bits32(opcode, 2, 0);
3088 Rn = Rd;
3089 Rm = Bits32(opcode, 5, 3);
3090 setflags = !InITBlock();
3091 break;
3092 case eEncodingT2:
3093 Rd = Bits32(opcode, 11, 8);
3094 Rn = Bits32(opcode, 19, 16);
3095 Rm = Bits32(opcode, 3, 0);
3096 setflags = BitIsSet(opcode, 20);
3097 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3098 return false;
3099 break;
3100 case eEncodingA1:
3101 Rd = Bits32(opcode, 15, 12);
3102 Rn = Bits32(opcode, 3, 0);
3103 Rm = Bits32(opcode, 11, 8);
3104 setflags = BitIsSet(opcode, 20);
3105 if (Rd == 15 || Rn == 15 || Rm == 15)
3106 return false;
3107 break;
3108 default:
3109 return false;
3110 }
3111
3112 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003113 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003114 if (!success)
3115 return false;
3116 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003117 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003118 if (!success)
3119 return false;
3120
3121 // Get the shift amount.
3122 uint32_t amt = Bits32(val, 7, 0);
3123
Johnny Chene97c0d52011-02-18 19:32:20 +00003124 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003125
3126 // The context specifies that an immediate is to be moved into Rd.
3127 EmulateInstruction::Context context;
3128 context.type = EmulateInstruction::eContextImmediate;
3129 context.SetNoArgs ();
3130
Johnny Chen10530c22011-02-17 22:37:12 +00003131 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003132 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003133 }
3134 return true;
3135}
3136
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003137// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003138// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003139// can be written back to the base register.
3140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003141EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003142{
3143#if 0
3144 // ARM pseudo code...
3145 if ConditionPassed()
3146 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3147 address = R[n];
3148
3149 for i = 0 to 14
3150 if registers<i> == '1' then
3151 R[i] = MemA[address, 4]; address = address + 4;
3152 if registers<15> == '1' then
3153 LoadWritePC (MemA[address, 4]);
3154
3155 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3156 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3157
3158#endif
3159
3160 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003161
Greg Clayton7bc39082011-03-24 23:53:38 +00003162 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003163 {
3164 uint32_t n;
3165 uint32_t registers = 0;
3166 bool wback;
3167 const uint32_t addr_byte_size = GetAddressByteSize();
3168 switch (encoding)
3169 {
3170 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003171 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003172 n = Bits32 (opcode, 10, 8);
3173 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003174 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003175 wback = BitIsClear (registers, n);
3176 // if BitCount(registers) < 1 then UNPREDICTABLE;
3177 if (BitCount(registers) < 1)
3178 return false;
3179 break;
3180 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003181 // if W == '1' && Rn == '1101' then SEE POP;
3182 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003183 n = Bits32 (opcode, 19, 16);
3184 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003185 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003186 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003187
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003188 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003189 if ((n == 15)
3190 || (BitCount (registers) < 2)
3191 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3192 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003193
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003194 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003195 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003196 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003197
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003198 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003199 if (wback
3200 && BitIsSet (registers, n))
3201 return false;
3202 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003203
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003204 case eEncodingA1:
3205 n = Bits32 (opcode, 19, 16);
3206 registers = Bits32 (opcode, 15, 0);
3207 wback = BitIsSet (opcode, 21);
3208 if ((n == 15)
3209 || (BitCount (registers) < 1))
3210 return false;
3211 break;
3212 default:
3213 return false;
3214 }
3215
3216 int32_t offset = 0;
3217 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3218 if (!success)
3219 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003220
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003221 EmulateInstruction::Context context;
3222 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3223 Register dwarf_reg;
3224 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3225 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003226
3227 for (int i = 0; i < 14; ++i)
3228 {
3229 if (BitIsSet (registers, i))
3230 {
Caroline Tice85aab332011-02-08 23:56:10 +00003231 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003232 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003233 if (wback && (n == 13)) // Pop Instruction
3234 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3235
3236 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003237 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003238 if (!success)
3239 return false;
3240
3241 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3242 return false;
3243
3244 offset += addr_byte_size;
3245 }
3246 }
3247
3248 if (BitIsSet (registers, 15))
3249 {
3250 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003251 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003252 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003253 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003254 if (!success)
3255 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003256 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003257 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003258 return false;
3259 }
3260
3261 if (wback && BitIsClear (registers, n))
3262 {
Caroline Ticefa172202011-02-11 22:49:54 +00003263 // R[n] = R[n] + 4 * BitCount (registers)
3264 int32_t offset = addr_byte_size * BitCount (registers);
3265 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003266 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003267
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3269 return false;
3270 }
3271 if (wback && BitIsSet (registers, n))
3272 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003273 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003274 }
3275 return true;
3276}
Caroline Tice713c2662011-02-11 17:59:55 +00003277
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003278// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3279// The consecutive memory locations end at this address and the address just below the lowest of those locations
3280// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003281bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003282EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003283{
3284#if 0
3285 // ARM pseudo code...
3286 if ConditionPassed() then
3287 EncodingSpecificOperations();
3288 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003289
Caroline Tice713c2662011-02-11 17:59:55 +00003290 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003291 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003292 R[i] = MemA[address,4]; address = address + 4;
3293
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003294 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003295 LoadWritePC(MemA[address,4]);
3296
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003297 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3298 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003299#endif
3300
3301 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003302
Greg Clayton7bc39082011-03-24 23:53:38 +00003303 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003304 {
3305 uint32_t n;
3306 uint32_t registers = 0;
3307 bool wback;
3308 const uint32_t addr_byte_size = GetAddressByteSize();
3309
3310 // EncodingSpecificOperations();
3311 switch (encoding)
3312 {
3313 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003314 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003315 n = Bits32 (opcode, 19, 16);
3316 registers = Bits32 (opcode, 15, 0);
3317 wback = BitIsSet (opcode, 21);
3318
3319 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3320 if ((n == 15) || (BitCount (registers) < 1))
3321 return false;
3322
3323 break;
3324
3325 default:
3326 return false;
3327 }
3328 // address = R[n] - 4*BitCount(registers) + 4;
3329
3330 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003331 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003332
3333 if (!success)
3334 return false;
3335
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003336 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003337
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003338 EmulateInstruction::Context context;
3339 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3340 Register dwarf_reg;
3341 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3342 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003343
3344 // for i = 0 to 14
3345 for (int i = 0; i < 14; ++i)
3346 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003347 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003348 if (BitIsSet (registers, i))
3349 {
3350 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003351 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003352 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003353 if (!success)
3354 return false;
3355 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3356 return false;
3357 offset += addr_byte_size;
3358 }
3359 }
3360
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003361 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003362 // LoadWritePC(MemA[address,4]);
3363 if (BitIsSet (registers, 15))
3364 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003365 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003366 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003367 if (!success)
3368 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003369 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003370 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003371 return false;
3372 }
3373
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003374 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003375 if (wback && BitIsClear (registers, n))
3376 {
Caroline Tice713c2662011-02-11 17:59:55 +00003377 if (!success)
3378 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003379
3380 offset = (addr_byte_size * BitCount (registers)) * -1;
3381 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003382 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003383 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003384 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3385 return false;
3386 }
3387
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003388 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003389 if (wback && BitIsSet (registers, n))
3390 return WriteBits32Unknown (n);
3391 }
3392 return true;
3393}
3394
3395// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3396// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3397// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003398bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003399EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003400{
3401#if 0
3402 // ARM pseudo code...
3403 if ConditionPassed() then
3404 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3405 address = R[n] - 4*BitCount(registers);
3406
3407 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003408 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003409 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003410 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003411 LoadWritePC(MemA[address,4]);
3412
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003413 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3414 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003415#endif
3416
3417 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003418
Greg Clayton7bc39082011-03-24 23:53:38 +00003419 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003420 {
3421 uint32_t n;
3422 uint32_t registers = 0;
3423 bool wback;
3424 const uint32_t addr_byte_size = GetAddressByteSize();
3425 switch (encoding)
3426 {
3427 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003428 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003429 n = Bits32 (opcode, 19, 16);
3430 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003431 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003432 wback = BitIsSet (opcode, 21);
3433
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003434 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003435 if ((n == 15)
3436 || (BitCount (registers) < 2)
3437 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3438 return false;
3439
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003440 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003441 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003442 return false;
3443
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003444 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003445 if (wback && BitIsSet (registers, n))
3446 return false;
3447
3448 break;
3449
3450 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003451 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003452 n = Bits32 (opcode, 19, 16);
3453 registers = Bits32 (opcode, 15, 0);
3454 wback = BitIsSet (opcode, 21);
3455
3456 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3457 if ((n == 15) || (BitCount (registers) < 1))
3458 return false;
3459
3460 break;
3461
3462 default:
3463 return false;
3464 }
3465
Caroline Tice713c2662011-02-11 17:59:55 +00003466 // address = R[n] - 4*BitCount(registers);
3467
Caroline Tice0b29e242011-02-08 23:16:02 +00003468 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003469 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003470
3471 if (!success)
3472 return false;
3473
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003474 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003475 EmulateInstruction::Context context;
3476 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3477 Register dwarf_reg;
3478 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003479 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003480
3481 for (int i = 0; i < 14; ++i)
3482 {
3483 if (BitIsSet (registers, i))
3484 {
3485 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003486 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003487 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003488 if (!success)
3489 return false;
3490
3491 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3492 return false;
3493
3494 offset += addr_byte_size;
3495 }
3496 }
3497
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003498 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003499 // LoadWritePC(MemA[address,4]);
3500 if (BitIsSet (registers, 15))
3501 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003502 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003503 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003504 if (!success)
3505 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003506 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003507 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003508 return false;
3509 }
3510
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003511 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003512 if (wback && BitIsClear (registers, n))
3513 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003514 if (!success)
3515 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003516
3517 offset = (addr_byte_size * BitCount (registers)) * -1;
3518 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003519 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003520 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3522 return false;
3523 }
3524
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003525 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003526 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003527 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003528 }
3529 return true;
3530}
Caroline Tice85aab332011-02-08 23:56:10 +00003531
Caroline Tice713c2662011-02-11 17:59:55 +00003532// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3533// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3534// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003535bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003536EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003537{
3538#if 0
3539 if ConditionPassed() then
3540 EncodingSpecificOperations();
3541 address = R[n] + 4;
3542
3543 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003544 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003545 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003546 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003547 LoadWritePC(MemA[address,4]);
3548
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003549 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3550 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003551#endif
3552
3553 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003554
Greg Clayton7bc39082011-03-24 23:53:38 +00003555 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003556 {
3557 uint32_t n;
3558 uint32_t registers = 0;
3559 bool wback;
3560 const uint32_t addr_byte_size = GetAddressByteSize();
3561 switch (encoding)
3562 {
3563 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003564 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003565 n = Bits32 (opcode, 19, 16);
3566 registers = Bits32 (opcode, 15, 0);
3567 wback = BitIsSet (opcode, 21);
3568
3569 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3570 if ((n == 15) || (BitCount (registers) < 1))
3571 return false;
3572
3573 break;
3574 default:
3575 return false;
3576 }
3577 // address = R[n] + 4;
3578
3579 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003580 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003581
3582 if (!success)
3583 return false;
3584
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003585 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003586
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003587 EmulateInstruction::Context context;
3588 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3589 Register dwarf_reg;
3590 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3591 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003592
3593 for (int i = 0; i < 14; ++i)
3594 {
3595 if (BitIsSet (registers, i))
3596 {
3597 // R[i] = MemA[address,4]; address = address + 4;
3598
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003599 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003600 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003601 if (!success)
3602 return false;
3603
3604 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3605 return false;
3606
3607 offset += addr_byte_size;
3608 }
3609 }
3610
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003611 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003612 // LoadWritePC(MemA[address,4]);
3613 if (BitIsSet (registers, 15))
3614 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003615 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003616 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003617 if (!success)
3618 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003619 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003620 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003621 return false;
3622 }
3623
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003624 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003625 if (wback && BitIsClear (registers, n))
3626 {
Caroline Tice85aab332011-02-08 23:56:10 +00003627 if (!success)
3628 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003629
3630 offset = addr_byte_size * BitCount (registers);
3631 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003632 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003633 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3635 return false;
3636 }
3637
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003638 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003639 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003640 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003641 }
3642 return true;
3643}
Caroline Tice0b29e242011-02-08 23:16:02 +00003644
Johnny Chenef21b592011-02-10 01:52:38 +00003645// Load Register (immediate) calculates an address from a base register value and
3646// an immediate offset, loads a word from memory, and writes to a register.
3647// LDR (immediate, Thumb)
3648bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003649EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003650{
3651#if 0
3652 // ARM pseudo code...
3653 if (ConditionPassed())
3654 {
3655 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3656 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3657 address = if index then offset_addr else R[n];
3658 data = MemU[address,4];
3659 if wback then R[n] = offset_addr;
3660 if t == 15 then
3661 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3662 elsif UnalignedSupport() || address<1:0> = '00' then
3663 R[t] = data;
3664 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3665 }
3666#endif
3667
3668 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003669
Greg Clayton7bc39082011-03-24 23:53:38 +00003670 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003671 {
3672 uint32_t Rt; // the destination register
3673 uint32_t Rn; // the base register
3674 uint32_t imm32; // the immediate offset used to form the address
3675 addr_t offset_addr; // the offset address
3676 addr_t address; // the calculated address
3677 uint32_t data; // the literal data value from memory load
3678 bool add, index, wback;
3679 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003680 case eEncodingT1:
3681 Rt = Bits32(opcode, 5, 3);
3682 Rn = Bits32(opcode, 2, 0);
3683 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3684 // index = TRUE; add = TRUE; wback = FALSE
3685 add = true;
3686 index = true;
3687 wback = false;
3688
3689 break;
3690
3691 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003692 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003693 Rt = Bits32 (opcode, 10, 8);
3694 Rn = 13;
3695 imm32 = Bits32 (opcode, 7, 0) << 2;
3696
3697 // index = TRUE; add = TRUE; wback = FALSE;
3698 index = true;
3699 add = true;
3700 wback = false;
3701
3702 break;
3703
3704 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003705 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003706 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3707 Rt = Bits32 (opcode, 15, 12);
3708 Rn = Bits32 (opcode, 19, 16);
3709 imm32 = Bits32 (opcode, 11, 0);
3710
3711 // index = TRUE; add = TRUE; wback = FALSE;
3712 index = true;
3713 add = true;
3714 wback = false;
3715
3716 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3717 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3718 return false;
3719
3720 break;
3721
3722 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003723 // if Rn == '1111' then SEE LDR (literal);
3724 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3725 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3726 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003727 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3728 return false;
3729
3730 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3731 Rt = Bits32 (opcode, 15, 12);
3732 Rn = Bits32 (opcode, 19, 16);
3733 imm32 = Bits32 (opcode, 7, 0);
3734
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003735 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003736 index = BitIsSet (opcode, 10);
3737 add = BitIsSet (opcode, 9);
3738 wback = BitIsSet (opcode, 8);
3739
3740 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3741 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3742 return false;
3743
3744 break;
3745
3746 default:
3747 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003748 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003749 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003750 if (!success)
3751 return false;
3752 if (add)
3753 offset_addr = base + imm32;
3754 else
3755 offset_addr = base - imm32;
3756
3757 address = (index ? offset_addr : base);
3758
Caroline Ticebaf1f642011-03-24 19:23:45 +00003759 Register base_reg;
3760 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003761 if (wback)
3762 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003763 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003764 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3765 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003766
Johnny Chenef21b592011-02-10 01:52:38 +00003767 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3768 return false;
3769 }
3770
3771 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003772 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003773 context.type = EmulateInstruction::eContextRegisterLoad;
3774 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003775
3776 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003777 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003778 if (!success)
3779 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003780
3781 if (Rt == 15)
3782 {
3783 if (Bits32(address, 1, 0) == 0)
3784 {
Johnny Chen668b4512011-02-15 21:08:58 +00003785 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003786 return false;
3787 }
3788 else
3789 return false;
3790 }
3791 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3792 {
3793 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3794 return false;
3795 }
3796 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003797 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003798 }
3799 return true;
3800}
3801
Caroline Ticeaf556562011-02-15 18:42:15 +00003802// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3803// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3804// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003805bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003806EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003807{
3808#if 0
3809 if ConditionPassed() then
3810 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3811 address = R[n];
3812
3813 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003814 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003815 if i == n && wback && i != LowestSetBit(registers) then
3816 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3817 else
3818 MemA[address,4] = R[i];
3819 address = address + 4;
3820
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003821 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003822 MemA[address,4] = PCStoreValue();
3823 if wback then R[n] = R[n] + 4*BitCount(registers);
3824#endif
3825
3826 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003827
Greg Clayton7bc39082011-03-24 23:53:38 +00003828 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003829 {
3830 uint32_t n;
3831 uint32_t registers = 0;
3832 bool wback;
3833 const uint32_t addr_byte_size = GetAddressByteSize();
3834
3835 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3836 switch (encoding)
3837 {
3838 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003839 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003840 n = Bits32 (opcode, 10, 8);
3841 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003842 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003843 wback = true;
3844
3845 // if BitCount(registers) < 1 then UNPREDICTABLE;
3846 if (BitCount (registers) < 1)
3847 return false;
3848
3849 break;
3850
3851 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003852 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003853 n = Bits32 (opcode, 19, 16);
3854 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003855 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003856 wback = BitIsSet (opcode, 21);
3857
3858 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3859 if ((n == 15) || (BitCount (registers) < 2))
3860 return false;
3861
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003862 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003863 if (wback && BitIsSet (registers, n))
3864 return false;
3865
3866 break;
3867
3868 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003869 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003870 n = Bits32 (opcode, 19, 16);
3871 registers = Bits32 (opcode, 15, 0);
3872 wback = BitIsSet (opcode, 21);
3873
3874 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3875 if ((n == 15) || (BitCount (registers) < 1))
3876 return false;
3877
3878 break;
3879
3880 default:
3881 return false;
3882 }
3883
3884 // address = R[n];
3885 int32_t offset = 0;
3886 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3887 if (!success)
3888 return false;
3889
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003890 EmulateInstruction::Context context;
3891 context.type = EmulateInstruction::eContextRegisterStore;
3892 Register base_reg;
3893 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003894
3895 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003896 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003897 for (int i = 0; i < 14; ++i)
3898 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003899 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003900 if (BitIsSet (registers, i))
3901 {
3902 if (i < lowest_set_bit)
3903 lowest_set_bit = i;
3904 // if i == n && wback && i != LowestSetBit(registers) then
3905 if ((i == n) && wback && (i != lowest_set_bit))
3906 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3907 WriteBits32UnknownToMemory (address + offset);
3908 else
3909 {
3910 // MemA[address,4] = R[i];
3911 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3912 if (!success)
3913 return false;
3914
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003915 Register data_reg;
3916 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3917 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003918 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003919 return false;
3920 }
3921
3922 // address = address + 4;
3923 offset += addr_byte_size;
3924 }
3925 }
3926
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003927 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003928 // MemA[address,4] = PCStoreValue();
3929 if (BitIsSet (registers, 15))
3930 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003931 Register pc_reg;
3932 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3933 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003934 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003935 if (!success)
3936 return false;
3937
Caroline Tice8d681f52011-03-17 23:50:16 +00003938 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003939 return false;
3940 }
3941
3942 // if wback then R[n] = R[n] + 4*BitCount(registers);
3943 if (wback)
3944 {
3945 offset = addr_byte_size * BitCount (registers);
3946 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003947 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003948 addr_t data = address + offset;
3949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3950 return false;
3951 }
3952 }
3953 return true;
3954}
3955
Caroline Ticeaf556562011-02-15 18:42:15 +00003956// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3957// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3958// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003959bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003960EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00003961{
3962#if 0
3963 if ConditionPassed() then
3964 EncodingSpecificOperations();
3965 address = R[n] - 4*BitCount(registers) + 4;
3966
3967 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003968 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003969 if i == n && wback && i != LowestSetBit(registers) then
3970 MemA[address,4] = bits(32) UNKNOWN;
3971 else
3972 MemA[address,4] = R[i];
3973 address = address + 4;
3974
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003975 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003976 MemA[address,4] = PCStoreValue();
3977
3978 if wback then R[n] = R[n] - 4*BitCount(registers);
3979#endif
3980
3981 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00003982
Greg Clayton7bc39082011-03-24 23:53:38 +00003983 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00003984 {
3985 uint32_t n;
3986 uint32_t registers = 0;
3987 bool wback;
3988 const uint32_t addr_byte_size = GetAddressByteSize();
3989
3990 // EncodingSpecificOperations();
3991 switch (encoding)
3992 {
3993 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003994 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00003995 n = Bits32 (opcode, 19, 16);
3996 registers = Bits32 (opcode, 15, 0);
3997 wback = BitIsSet (opcode, 21);
3998
3999 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4000 if ((n == 15) || (BitCount (registers) < 1))
4001 return false;
4002 break;
4003 default:
4004 return false;
4005 }
4006
4007 // address = R[n] - 4*BitCount(registers) + 4;
4008 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004009 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004010 if (!success)
4011 return false;
4012
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004013 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004014
4015 EmulateInstruction::Context context;
4016 context.type = EmulateInstruction::eContextRegisterStore;
4017 Register base_reg;
4018 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4019
4020 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004021 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004022 for (int i = 0; i < 14; ++i)
4023 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004024 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004025 if (BitIsSet (registers, i))
4026 {
4027 if (i < lowest_bit_set)
4028 lowest_bit_set = i;
4029 //if i == n && wback && i != LowestSetBit(registers) then
4030 if ((i == n) && wback && (i != lowest_bit_set))
4031 // MemA[address,4] = bits(32) UNKNOWN;
4032 WriteBits32UnknownToMemory (address + offset);
4033 else
4034 {
4035 // MemA[address,4] = R[i];
4036 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4037 if (!success)
4038 return false;
4039
4040 Register data_reg;
4041 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004042 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004043 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004044 return false;
4045 }
4046
4047 // address = address + 4;
4048 offset += addr_byte_size;
4049 }
4050 }
4051
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004052 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004053 // MemA[address,4] = PCStoreValue();
4054 if (BitIsSet (registers, 15))
4055 {
4056 Register pc_reg;
4057 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4058 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004059 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004060 if (!success)
4061 return false;
4062
Caroline Tice8d681f52011-03-17 23:50:16 +00004063 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004064 return false;
4065 }
4066
4067 // if wback then R[n] = R[n] - 4*BitCount(registers);
4068 if (wback)
4069 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004070 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004071 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4072 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004073 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004074 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4075 return false;
4076 }
4077 }
4078 return true;
4079}
4080
Caroline Ticeaf556562011-02-15 18:42:15 +00004081// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4082// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4083// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004084bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004085EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004086{
4087#if 0
4088 if ConditionPassed() then
4089 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4090 address = R[n] - 4*BitCount(registers);
4091
4092 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004093 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004094 if i == n && wback && i != LowestSetBit(registers) then
4095 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4096 else
4097 MemA[address,4] = R[i];
4098 address = address + 4;
4099
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004100 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004101 MemA[address,4] = PCStoreValue();
4102
4103 if wback then R[n] = R[n] - 4*BitCount(registers);
4104#endif
4105
4106
4107 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004108
Greg Clayton7bc39082011-03-24 23:53:38 +00004109 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004110 {
4111 uint32_t n;
4112 uint32_t registers = 0;
4113 bool wback;
4114 const uint32_t addr_byte_size = GetAddressByteSize();
4115
4116 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4117 switch (encoding)
4118 {
4119 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004120 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004121 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4122 {
4123 // See PUSH
4124 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004125 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004126 n = Bits32 (opcode, 19, 16);
4127 registers = Bits32 (opcode, 15, 0);
4128 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4129 wback = BitIsSet (opcode, 21);
4130 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4131 if ((n == 15) || BitCount (registers) < 2)
4132 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004133 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004134 if (wback && BitIsSet (registers, n))
4135 return false;
4136 break;
4137
4138 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004139 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004140 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4141 {
4142 // See Push
4143 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004144 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004145 n = Bits32 (opcode, 19, 16);
4146 registers = Bits32 (opcode, 15, 0);
4147 wback = BitIsSet (opcode, 21);
4148 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4149 if ((n == 15) || BitCount (registers) < 1)
4150 return false;
4151 break;
4152
4153 default:
4154 return false;
4155 }
4156
4157 // address = R[n] - 4*BitCount(registers);
4158
4159 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004160 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004161 if (!success)
4162 return false;
4163
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004164 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004165
4166 EmulateInstruction::Context context;
4167 context.type = EmulateInstruction::eContextRegisterStore;
4168 Register base_reg;
4169 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4170
4171 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004172 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004173 for (int i = 0; i < 14; ++i)
4174 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004175 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004176 if (BitIsSet (registers, i))
4177 {
4178 if (i < lowest_set_bit)
4179 lowest_set_bit = i;
4180 // if i == n && wback && i != LowestSetBit(registers) then
4181 if ((i == n) && wback && (i != lowest_set_bit))
4182 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4183 WriteBits32UnknownToMemory (address + offset);
4184 else
4185 {
4186 // MemA[address,4] = R[i];
4187 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4188 if (!success)
4189 return false;
4190
4191 Register data_reg;
4192 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004193 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004194 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004195 return false;
4196 }
4197
4198 // address = address + 4;
4199 offset += addr_byte_size;
4200 }
4201 }
4202
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004203 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004204 // MemA[address,4] = PCStoreValue();
4205 if (BitIsSet (registers, 15))
4206 {
4207 Register pc_reg;
4208 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4209 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004210 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004211 if (!success)
4212 return false;
4213
Caroline Tice8d681f52011-03-17 23:50:16 +00004214 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004215 return false;
4216 }
4217
4218 // if wback then R[n] = R[n] - 4*BitCount(registers);
4219 if (wback)
4220 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004221 offset = (addr_byte_size * BitCount (registers)) * -1;
4222 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4223 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004224 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004225 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4226 return false;
4227 }
4228 }
4229 return true;
4230}
4231
4232// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4233// from a base register. The consecutive memory locations start just above this address, and the address of the last
4234// of those locations can optionally be written back to the base register.
4235bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004236EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004237{
4238#if 0
4239 if ConditionPassed() then
4240 EncodingSpecificOperations();
4241 address = R[n] + 4;
4242
4243 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004244 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004245 if i == n && wback && i != LowestSetBit(registers) then
4246 MemA[address,4] = bits(32) UNKNOWN;
4247 else
4248 MemA[address,4] = R[i];
4249 address = address + 4;
4250
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004251 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004252 MemA[address,4] = PCStoreValue();
4253
4254 if wback then R[n] = R[n] + 4*BitCount(registers);
4255#endif
4256
4257 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004258
Greg Clayton7bc39082011-03-24 23:53:38 +00004259 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004260 {
4261 uint32_t n;
4262 uint32_t registers = 0;
4263 bool wback;
4264 const uint32_t addr_byte_size = GetAddressByteSize();
4265
4266 // EncodingSpecificOperations();
4267 switch (encoding)
4268 {
4269 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004270 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004271 n = Bits32 (opcode, 19, 16);
4272 registers = Bits32 (opcode, 15, 0);
4273 wback = BitIsSet (opcode, 21);
4274
4275 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4276 if ((n == 15) && (BitCount (registers) < 1))
4277 return false;
4278 break;
4279 default:
4280 return false;
4281 }
4282 // address = R[n] + 4;
4283
4284 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004285 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004286 if (!success)
4287 return false;
4288
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004289 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004290
4291 EmulateInstruction::Context context;
4292 context.type = EmulateInstruction::eContextRegisterStore;
4293 Register base_reg;
4294 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4295
4296 uint32_t lowest_set_bit = 14;
4297 // for i = 0 to 14
4298 for (int i = 0; i < 14; ++i)
4299 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004300 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004301 if (BitIsSet (registers, i))
4302 {
4303 if (i < lowest_set_bit)
4304 lowest_set_bit = i;
4305 // if i == n && wback && i != LowestSetBit(registers) then
4306 if ((i == n) && wback && (i != lowest_set_bit))
4307 // MemA[address,4] = bits(32) UNKNOWN;
4308 WriteBits32UnknownToMemory (address + offset);
4309 // else
4310 else
4311 {
4312 // MemA[address,4] = R[i];
4313 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4314 if (!success)
4315 return false;
4316
4317 Register data_reg;
4318 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004319 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004320 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004321 return false;
4322 }
4323
4324 // address = address + 4;
4325 offset += addr_byte_size;
4326 }
4327 }
4328
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004329 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004330 // MemA[address,4] = PCStoreValue();
4331 if (BitIsSet (registers, 15))
4332 {
4333 Register pc_reg;
4334 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4335 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004336 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004337 if (!success)
4338 return false;
4339
Caroline Tice8d681f52011-03-17 23:50:16 +00004340 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004341 return false;
4342 }
4343
4344 // if wback then R[n] = R[n] + 4*BitCount(registers);
4345 if (wback)
4346 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004347 offset = addr_byte_size * BitCount (registers);
4348 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4349 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004350 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004351 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4352 return false;
4353 }
4354 }
4355 return true;
4356}
Caroline Tice7fac8572011-02-15 22:53:54 +00004357
4358// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4359// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4360bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004361EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004362{
4363#if 0
4364 if ConditionPassed() then
4365 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4366 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4367 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004368 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004369 MemU[address,4] = R[t];
4370 else // Can only occur before ARMv7
4371 MemU[address,4] = bits(32) UNKNOWN;
4372 if wback then R[n] = offset_addr;
4373#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004374
Caroline Tice7fac8572011-02-15 22:53:54 +00004375 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004376
Greg Clayton7bc39082011-03-24 23:53:38 +00004377 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004378 {
4379 const uint32_t addr_byte_size = GetAddressByteSize();
4380
4381 uint32_t t;
4382 uint32_t n;
4383 uint32_t imm32;
4384 bool index;
4385 bool add;
4386 bool wback;
4387 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4388 switch (encoding)
4389 {
4390 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004391 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004392 t = Bits32 (opcode, 2, 0);
4393 n = Bits32 (opcode, 5, 3);
4394 imm32 = Bits32 (opcode, 10, 6) << 2;
4395
4396 // index = TRUE; add = TRUE; wback = FALSE;
4397 index = true;
4398 add = false;
4399 wback = false;
4400 break;
4401
4402 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004403 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004404 t = Bits32 (opcode, 10, 8);
4405 n = 13;
4406 imm32 = Bits32 (opcode, 7, 0) << 2;
4407
4408 // index = TRUE; add = TRUE; wback = FALSE;
4409 index = true;
4410 add = true;
4411 wback = false;
4412 break;
4413
4414 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004415 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004416 if (Bits32 (opcode, 19, 16) == 15)
4417 return false;
4418
4419 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4420 t = Bits32 (opcode, 15, 12);
4421 n = Bits32 (opcode, 19, 16);
4422 imm32 = Bits32 (opcode, 11, 0);
4423
4424 // index = TRUE; add = TRUE; wback = FALSE;
4425 index = true;
4426 add = true;
4427 wback = false;
4428
4429 // if t == 15 then UNPREDICTABLE;
4430 if (t == 15)
4431 return false;
4432 break;
4433
4434 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004435 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4436 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4437 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004438 if ((Bits32 (opcode, 19, 16) == 15)
4439 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4440 return false;
4441
4442 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4443 t = Bits32 (opcode, 15, 12);
4444 n = Bits32 (opcode, 19, 16);
4445 imm32 = Bits32 (opcode, 7, 0);
4446
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004447 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004448 index = BitIsSet (opcode, 10);
4449 add = BitIsSet (opcode, 9);
4450 wback = BitIsSet (opcode, 8);
4451
4452 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4453 if ((t == 15) || (wback && (n == t)))
4454 return false;
4455 break;
4456
4457 default:
4458 return false;
4459 }
4460
4461 addr_t offset_addr;
4462 addr_t address;
4463
4464 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004465 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004466 if (!success)
4467 return false;
4468
4469 if (add)
4470 offset_addr = base_address + imm32;
4471 else
4472 offset_addr = base_address - imm32;
4473
4474 // address = if index then offset_addr else R[n];
4475 if (index)
4476 address = offset_addr;
4477 else
4478 address = base_address;
4479
4480 EmulateInstruction::Context context;
4481 context.type = eContextRegisterStore;
4482 Register base_reg;
4483 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4484
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004485 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004486 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4487 {
4488 // MemU[address,4] = R[t];
4489 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4490 if (!success)
4491 return false;
4492
4493 Register data_reg;
4494 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4495 int32_t offset = address - base_address;
4496 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004497 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004498 return false;
4499 }
4500 else
4501 {
4502 // MemU[address,4] = bits(32) UNKNOWN;
4503 WriteBits32UnknownToMemory (address);
4504 }
4505
4506 // if wback then R[n] = offset_addr;
4507 if (wback)
4508 {
4509 context.type = eContextRegisterLoad;
4510 context.SetAddress (offset_addr);
4511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4512 return false;
4513 }
4514 }
4515 return true;
4516}
Caroline Ticeaf556562011-02-15 18:42:15 +00004517
Caroline Tice3fd63e92011-02-16 00:33:43 +00004518// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4519// word from a register to memory. The offset register value can optionally be shifted.
4520bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004521EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004522{
4523#if 0
4524 if ConditionPassed() then
4525 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4526 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4527 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4528 address = if index then offset_addr else R[n];
4529 if t == 15 then // Only possible for encoding A1
4530 data = PCStoreValue();
4531 else
4532 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004533 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004534 MemU[address,4] = data;
4535 else // Can only occur before ARMv7
4536 MemU[address,4] = bits(32) UNKNOWN;
4537 if wback then R[n] = offset_addr;
4538#endif
4539
4540 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004541
Greg Clayton7bc39082011-03-24 23:53:38 +00004542 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004543 {
4544 const uint32_t addr_byte_size = GetAddressByteSize();
4545
4546 uint32_t t;
4547 uint32_t n;
4548 uint32_t m;
4549 ARM_ShifterType shift_t;
4550 uint32_t shift_n;
4551 bool index;
4552 bool add;
4553 bool wback;
4554
4555 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4556 switch (encoding)
4557 {
4558 case eEncodingT1:
4559 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4560 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4561 t = Bits32 (opcode, 2, 0);
4562 n = Bits32 (opcode, 5, 3);
4563 m = Bits32 (opcode, 8, 6);
4564
4565 // index = TRUE; add = TRUE; wback = FALSE;
4566 index = true;
4567 add = true;
4568 wback = false;
4569
4570 // (shift_t, shift_n) = (SRType_LSL, 0);
4571 shift_t = SRType_LSL;
4572 shift_n = 0;
4573 break;
4574
4575 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004576 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004577 if (Bits32 (opcode, 19, 16) == 15)
4578 return false;
4579
4580 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4581 t = Bits32 (opcode, 15, 12);
4582 n = Bits32 (opcode, 19, 16);
4583 m = Bits32 (opcode, 3, 0);
4584
4585 // index = TRUE; add = TRUE; wback = FALSE;
4586 index = true;
4587 add = true;
4588 wback = false;
4589
4590 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4591 shift_t = SRType_LSL;
4592 shift_n = Bits32 (opcode, 5, 4);
4593
4594 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4595 if ((t == 15) || (BadReg (m)))
4596 return false;
4597 break;
4598
4599 case eEncodingA1:
4600 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004601 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004602 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4603 t = Bits32 (opcode, 15, 12);
4604 n = Bits32 (opcode, 19, 16);
4605 m = Bits32 (opcode, 3, 0);
4606
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004607 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004608 index = BitIsSet (opcode, 24);
4609 add = BitIsSet (opcode, 23);
4610 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4611
4612 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4613 uint32_t typ = Bits32 (opcode, 6, 5);
4614 uint32_t imm5 = Bits32 (opcode, 11, 7);
4615 shift_n = DecodeImmShift(typ, imm5, shift_t);
4616
4617 // if m == 15 then UNPREDICTABLE;
4618 if (m == 15)
4619 return false;
4620
4621 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4622 if (wback && ((n == 15) || (n == t)))
4623 return false;
4624
4625 break;
4626 }
4627 default:
4628 return false;
4629 }
4630
4631 addr_t offset_addr;
4632 addr_t address;
4633 int32_t offset = 0;
4634
4635 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4636 if (!success)
4637 return false;
4638
4639 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4640 if (!success)
4641 return false;
4642
4643 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004644 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004645
4646 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4647 if (add)
4648 offset_addr = base_address + offset;
4649 else
4650 offset_addr = base_address - offset;
4651
4652 // address = if index then offset_addr else R[n];
4653 if (index)
4654 address = offset_addr;
4655 else
4656 address = base_address;
4657
4658 uint32_t data;
4659 // if t == 15 then // Only possible for encoding A1
4660 if (t == 15)
4661 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004662 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004663 else
4664 // data = R[t];
4665 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4666
4667 if (!success)
4668 return false;
4669
4670 EmulateInstruction::Context context;
4671 context.type = eContextRegisterStore;
4672
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004673 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004674 if (UnalignedSupport ()
4675 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4676 || CurrentInstrSet() == eModeARM)
4677 {
4678 // MemU[address,4] = data;
4679
4680 Register base_reg;
4681 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4682
4683 Register data_reg;
4684 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4685
4686 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004687 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004688 return false;
4689
4690 }
4691 else
4692 // MemU[address,4] = bits(32) UNKNOWN;
4693 WriteBits32UnknownToMemory (address);
4694
4695 // if wback then R[n] = offset_addr;
4696 if (wback)
4697 {
4698 context.type = eContextRegisterLoad;
4699 context.SetAddress (offset_addr);
4700 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4701 return false;
4702 }
4703
4704 }
4705 return true;
4706}
Caroline Tice73a29de2011-02-16 20:22:22 +00004707
4708bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004709EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004710{
4711#if 0
4712 if ConditionPassed() then
4713 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4714 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4715 address = if index then offset_addr else R[n];
4716 MemU[address,1] = R[t]<7:0>;
4717 if wback then R[n] = offset_addr;
4718#endif
4719
4720
4721 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004722
Greg Clayton7bc39082011-03-24 23:53:38 +00004723 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004724 {
4725 uint32_t t;
4726 uint32_t n;
4727 uint32_t imm32;
4728 bool index;
4729 bool add;
4730 bool wback;
4731 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4732 switch (encoding)
4733 {
4734 case eEncodingT1:
4735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4736 t = Bits32 (opcode, 2, 0);
4737 n = Bits32 (opcode, 5, 3);
4738 imm32 = Bits32 (opcode, 10, 6);
4739
4740 // index = TRUE; add = TRUE; wback = FALSE;
4741 index = true;
4742 add = true;
4743 wback = false;
4744 break;
4745
4746 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004747 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004748 if (Bits32 (opcode, 19, 16) == 15)
4749 return false;
4750
4751 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4752 t = Bits32 (opcode, 15, 12);
4753 n = Bits32 (opcode, 19, 16);
4754 imm32 = Bits32 (opcode, 11, 0);
4755
4756 // index = TRUE; add = TRUE; wback = FALSE;
4757 index = true;
4758 add = true;
4759 wback = false;
4760
4761 // if BadReg(t) then UNPREDICTABLE;
4762 if (BadReg (t))
4763 return false;
4764 break;
4765
4766 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004767 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4768 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004769 if (Bits32 (opcode, 19, 16) == 15)
4770 return false;
4771
4772 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4773 t = Bits32 (opcode, 15, 12);
4774 n = Bits32 (opcode, 19, 16);
4775 imm32 = Bits32 (opcode, 7, 0);
4776
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004777 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004778 index = BitIsSet (opcode, 10);
4779 add = BitIsSet (opcode, 9);
4780 wback = BitIsSet (opcode, 8);
4781
4782 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4783 if ((BadReg (t)) || (wback && (n == t)))
4784 return false;
4785 break;
4786
4787 default:
4788 return false;
4789 }
4790
4791 addr_t offset_addr;
4792 addr_t address;
4793 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4794 if (!success)
4795 return false;
4796
4797 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4798 if (add)
4799 offset_addr = base_address + imm32;
4800 else
4801 offset_addr = base_address - imm32;
4802
4803 // address = if index then offset_addr else R[n];
4804 if (index)
4805 address = offset_addr;
4806 else
4807 address = base_address;
4808
Caroline Ticecc96eb52011-02-17 19:20:40 +00004809 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004810 Register base_reg;
4811 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4812
4813 Register data_reg;
4814 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4815
4816 EmulateInstruction::Context context;
4817 context.type = eContextRegisterStore;
4818 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4819
4820 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4821 if (!success)
4822 return false;
4823
4824 data = Bits32 (data, 7, 0);
4825
Caroline Ticecc96eb52011-02-17 19:20:40 +00004826 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004827 return false;
4828
4829 // if wback then R[n] = offset_addr;
4830 if (wback)
4831 {
4832 context.type = eContextRegisterLoad;
4833 context.SetAddress (offset_addr);
4834 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4835 return false;
4836 }
4837
4838 }
4839
4840 return true;
4841}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004842
4843// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4844// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4845bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004846EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004847{
4848#if 0
4849 if ConditionPassed() then
4850 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4851 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4852 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4853 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004854 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004855 MemU[address,2] = R[t]<15:0>;
4856 else // Can only occur before ARMv7
4857 MemU[address,2] = bits(16) UNKNOWN;
4858 if wback then R[n] = offset_addr;
4859#endif
4860
4861 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004862
Greg Clayton7bc39082011-03-24 23:53:38 +00004863 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004864 {
4865 uint32_t t;
4866 uint32_t n;
4867 uint32_t m;
4868 bool index;
4869 bool add;
4870 bool wback;
4871 ARM_ShifterType shift_t;
4872 uint32_t shift_n;
4873
4874 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4875 switch (encoding)
4876 {
4877 case eEncodingT1:
4878 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4879 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4880 t = Bits32 (opcode, 2, 0);
4881 n = Bits32 (opcode, 5, 3);
4882 m = Bits32 (opcode, 8, 6);
4883
4884 // index = TRUE; add = TRUE; wback = FALSE;
4885 index = true;
4886 add = true;
4887 wback = false;
4888
4889 // (shift_t, shift_n) = (SRType_LSL, 0);
4890 shift_t = SRType_LSL;
4891 shift_n = 0;
4892
4893 break;
4894
4895 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004896 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004897 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4898 t = Bits32 (opcode, 15, 12);
4899 n = Bits32 (opcode, 19, 16);
4900 m = Bits32 (opcode, 3, 0);
4901 if (n == 15)
4902 return false;
4903
4904 // index = TRUE; add = TRUE; wback = FALSE;
4905 index = true;
4906 add = true;
4907 wback = false;
4908
4909 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4910 shift_t = SRType_LSL;
4911 shift_n = Bits32 (opcode, 5, 4);
4912
4913 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4914 if (BadReg (t) || BadReg (m))
4915 return false;
4916
4917 break;
4918
4919 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004920 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004921 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4922 t = Bits32 (opcode, 15, 12);
4923 n = Bits32 (opcode, 19, 16);
4924 m = Bits32 (opcode, 3, 0);
4925
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004926 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004927 index = BitIsSet (opcode, 24);
4928 add = BitIsSet (opcode, 23);
4929 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4930
4931 // (shift_t, shift_n) = (SRType_LSL, 0);
4932 shift_t = SRType_LSL;
4933 shift_n = 0;
4934
4935 // if t == 15 || m == 15 then UNPREDICTABLE;
4936 if ((t == 15) || (m == 15))
4937 return false;
4938
4939 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4940 if (wback && ((n == 15) || (n == t)))
4941 return false;
4942
4943 break;
4944
4945 default:
4946 return false;
4947 }
4948
4949 uint32_t Rm = ReadCoreReg (m, &success);
4950 if (!success)
4951 return false;
4952
4953 uint32_t Rn = ReadCoreReg (n, &success);
4954 if (!success)
4955 return false;
4956
4957 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4958 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4959
4960 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4961 addr_t offset_addr;
4962 if (add)
4963 offset_addr = Rn + offset;
4964 else
4965 offset_addr = Rn - offset;
4966
4967 // address = if index then offset_addr else R[n];
4968 addr_t address;
4969 if (index)
4970 address = offset_addr;
4971 else
4972 address = Rn;
4973
4974 EmulateInstruction::Context context;
4975 context.type = eContextRegisterStore;
4976 Register base_reg;
4977 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4978 Register offset_reg;
4979 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4980
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004981 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004982 if (UnalignedSupport() || BitIsClear (address, 0))
4983 {
4984 // MemU[address,2] = R[t]<15:0>;
4985 uint32_t Rt = ReadCoreReg (t, &success);
4986 if (!success)
4987 return false;
4988
4989 EmulateInstruction::Context context;
4990 context.type = eContextRegisterStore;
4991 Register base_reg;
4992 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4993 Register offset_reg;
4994 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4995 Register data_reg;
4996 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4997 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
4998
4999 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5000 return false;
5001 }
5002 else // Can only occur before ARMv7
5003 {
5004 // MemU[address,2] = bits(16) UNKNOWN;
5005 }
5006
5007 // if wback then R[n] = offset_addr;
5008 if (wback)
5009 {
5010 context.type = eContextAdjustBaseRegister;
5011 context.SetAddress (offset_addr);
5012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5013 return false;
5014 }
5015 }
5016
5017 return true;
5018}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005019
Johnny Chen157b9592011-02-18 21:13:05 +00005020// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5021// and writes the result to the destination register. It can optionally update the condition flags
5022// based on the result.
5023bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005024EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005025{
5026#if 0
5027 // ARM pseudo code...
5028 if ConditionPassed() then
5029 EncodingSpecificOperations();
5030 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5031 if d == 15 then // Can only occur for ARM encoding
5032 ALUWritePC(result); // setflags is always FALSE here
5033 else
5034 R[d] = result;
5035 if setflags then
5036 APSR.N = result<31>;
5037 APSR.Z = IsZeroBit(result);
5038 APSR.C = carry;
5039 APSR.V = overflow;
5040#endif
5041
5042 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005043
Greg Clayton7bc39082011-03-24 23:53:38 +00005044 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005045 {
5046 uint32_t Rd, Rn;
5047 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5048 bool setflags;
5049 switch (encoding)
5050 {
5051 case eEncodingT1:
5052 Rd = Bits32(opcode, 11, 8);
5053 Rn = Bits32(opcode, 19, 16);
5054 setflags = BitIsSet(opcode, 20);
5055 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5056 if (BadReg(Rd) || BadReg(Rn))
5057 return false;
5058 break;
5059 case eEncodingA1:
5060 Rd = Bits32(opcode, 15, 12);
5061 Rn = Bits32(opcode, 19, 16);
5062 setflags = BitIsSet(opcode, 20);
5063 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5064 // TODO: Emulate SUBS PC, LR and related instructions.
5065 if (Rd == 15 && setflags)
5066 return false;
5067 break;
5068 default:
5069 return false;
5070 }
5071
5072 // Read the first operand.
5073 int32_t val1 = ReadCoreReg(Rn, &success);
5074 if (!success)
5075 return false;
5076
5077 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5078
5079 EmulateInstruction::Context context;
5080 context.type = EmulateInstruction::eContextImmediate;
5081 context.SetNoArgs ();
5082
5083 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5084 return false;
5085 }
5086 return true;
5087}
5088
5089// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5090// register value, and writes the result to the destination register. It can optionally update the
5091// condition flags based on the result.
5092bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005093EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005094{
5095#if 0
5096 // ARM pseudo code...
5097 if ConditionPassed() then
5098 EncodingSpecificOperations();
5099 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5100 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5101 if d == 15 then // Can only occur for ARM encoding
5102 ALUWritePC(result); // setflags is always FALSE here
5103 else
5104 R[d] = result;
5105 if setflags then
5106 APSR.N = result<31>;
5107 APSR.Z = IsZeroBit(result);
5108 APSR.C = carry;
5109 APSR.V = overflow;
5110#endif
5111
5112 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005113
Greg Clayton7bc39082011-03-24 23:53:38 +00005114 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005115 {
5116 uint32_t Rd, Rn, Rm;
5117 ARM_ShifterType shift_t;
5118 uint32_t shift_n; // the shift applied to the value read from Rm
5119 bool setflags;
5120 switch (encoding)
5121 {
5122 case eEncodingT1:
5123 Rd = Rn = Bits32(opcode, 2, 0);
5124 Rm = Bits32(opcode, 5, 3);
5125 setflags = !InITBlock();
5126 shift_t = SRType_LSL;
5127 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005128 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005129 case eEncodingT2:
5130 Rd = Bits32(opcode, 11, 8);
5131 Rn = Bits32(opcode, 19, 16);
5132 Rm = Bits32(opcode, 3, 0);
5133 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005134 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005135 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5136 return false;
5137 break;
5138 case eEncodingA1:
5139 Rd = Bits32(opcode, 15, 12);
5140 Rn = Bits32(opcode, 19, 16);
5141 Rm = Bits32(opcode, 3, 0);
5142 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005143 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005144 // TODO: Emulate SUBS PC, LR and related instructions.
5145 if (Rd == 15 && setflags)
5146 return false;
5147 break;
5148 default:
5149 return false;
5150 }
5151
5152 // Read the first operand.
5153 int32_t val1 = ReadCoreReg(Rn, &success);
5154 if (!success)
5155 return false;
5156
5157 // Read the second operand.
5158 int32_t val2 = ReadCoreReg(Rm, &success);
5159 if (!success)
5160 return false;
5161
5162 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5163 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5164
5165 EmulateInstruction::Context context;
5166 context.type = EmulateInstruction::eContextImmediate;
5167 context.SetNoArgs ();
5168
5169 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5170 return false;
5171 }
5172 return true;
5173}
5174
Johnny Chena695f952011-02-23 21:24:25 +00005175// This instruction adds an immediate value to the PC value to form a PC-relative address,
5176// and writes the result to the destination register.
5177bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005178EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005179{
5180#if 0
5181 // ARM pseudo code...
5182 if ConditionPassed() then
5183 EncodingSpecificOperations();
5184 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5185 if d == 15 then // Can only occur for ARM encodings
5186 ALUWritePC(result);
5187 else
5188 R[d] = result;
5189#endif
5190
5191 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005192
Greg Clayton7bc39082011-03-24 23:53:38 +00005193 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005194 {
5195 uint32_t Rd;
5196 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5197 bool add;
5198 switch (encoding)
5199 {
5200 case eEncodingT1:
5201 Rd = Bits32(opcode, 10, 8);
5202 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5203 break;
5204 case eEncodingT2:
5205 case eEncodingT3:
5206 Rd = Bits32(opcode, 11, 8);
5207 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5208 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5209 if (BadReg(Rd))
5210 return false;
5211 break;
5212 case eEncodingA1:
5213 case eEncodingA2:
5214 Rd = Bits32(opcode, 15, 12);
5215 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5216 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5217 break;
5218 default:
5219 return false;
5220 }
5221
5222 // Read the PC value.
5223 uint32_t pc = ReadCoreReg(PC_REG, &success);
5224 if (!success)
5225 return false;
5226
5227 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5228
5229 EmulateInstruction::Context context;
5230 context.type = EmulateInstruction::eContextImmediate;
5231 context.SetNoArgs ();
5232
5233 if (!WriteCoreReg(context, result, Rd))
5234 return false;
5235 }
5236 return true;
5237}
5238
Johnny Chene97c0d52011-02-18 19:32:20 +00005239// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5240// to the destination register. It can optionally update the condition flags based on the result.
5241bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005242EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005243{
5244#if 0
5245 // ARM pseudo code...
5246 if ConditionPassed() then
5247 EncodingSpecificOperations();
5248 result = R[n] AND imm32;
5249 if d == 15 then // Can only occur for ARM encoding
5250 ALUWritePC(result); // setflags is always FALSE here
5251 else
5252 R[d] = result;
5253 if setflags then
5254 APSR.N = result<31>;
5255 APSR.Z = IsZeroBit(result);
5256 APSR.C = carry;
5257 // APSR.V unchanged
5258#endif
5259
5260 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005261
Greg Clayton7bc39082011-03-24 23:53:38 +00005262 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005263 {
5264 uint32_t Rd, Rn;
5265 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5266 bool setflags;
5267 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5268 switch (encoding)
5269 {
5270 case eEncodingT1:
5271 Rd = Bits32(opcode, 11, 8);
5272 Rn = Bits32(opcode, 19, 16);
5273 setflags = BitIsSet(opcode, 20);
5274 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005275 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005276 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005277 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005278 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5279 return false;
5280 break;
5281 case eEncodingA1:
5282 Rd = Bits32(opcode, 15, 12);
5283 Rn = Bits32(opcode, 19, 16);
5284 setflags = BitIsSet(opcode, 20);
5285 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5286 // TODO: Emulate SUBS PC, LR and related instructions.
5287 if (Rd == 15 && setflags)
5288 return false;
5289 break;
5290 default:
5291 return false;
5292 }
5293
Johnny Chene97c0d52011-02-18 19:32:20 +00005294 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005295 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005296 if (!success)
5297 return false;
5298
5299 uint32_t result = val1 & imm32;
5300
5301 EmulateInstruction::Context context;
5302 context.type = EmulateInstruction::eContextImmediate;
5303 context.SetNoArgs ();
5304
5305 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5306 return false;
5307 }
5308 return true;
5309}
5310
5311// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5312// and writes the result to the destination register. It can optionally update the condition flags
5313// based on the result.
5314bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005315EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005316{
5317#if 0
5318 // ARM pseudo code...
5319 if ConditionPassed() then
5320 EncodingSpecificOperations();
5321 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5322 result = R[n] AND shifted;
5323 if d == 15 then // Can only occur for ARM encoding
5324 ALUWritePC(result); // setflags is always FALSE here
5325 else
5326 R[d] = result;
5327 if setflags then
5328 APSR.N = result<31>;
5329 APSR.Z = IsZeroBit(result);
5330 APSR.C = carry;
5331 // APSR.V unchanged
5332#endif
5333
5334 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005335
Greg Clayton7bc39082011-03-24 23:53:38 +00005336 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005337 {
5338 uint32_t Rd, Rn, Rm;
5339 ARM_ShifterType shift_t;
5340 uint32_t shift_n; // the shift applied to the value read from Rm
5341 bool setflags;
5342 uint32_t carry;
5343 switch (encoding)
5344 {
5345 case eEncodingT1:
5346 Rd = Rn = Bits32(opcode, 2, 0);
5347 Rm = Bits32(opcode, 5, 3);
5348 setflags = !InITBlock();
5349 shift_t = SRType_LSL;
5350 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005351 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005352 case eEncodingT2:
5353 Rd = Bits32(opcode, 11, 8);
5354 Rn = Bits32(opcode, 19, 16);
5355 Rm = Bits32(opcode, 3, 0);
5356 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005357 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005358 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005359 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005360 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005361 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5362 return false;
5363 break;
5364 case eEncodingA1:
5365 Rd = Bits32(opcode, 15, 12);
5366 Rn = Bits32(opcode, 19, 16);
5367 Rm = Bits32(opcode, 3, 0);
5368 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005369 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005370 // TODO: Emulate SUBS PC, LR and related instructions.
5371 if (Rd == 15 && setflags)
5372 return false;
5373 break;
5374 default:
5375 return false;
5376 }
5377
Johnny Chene97c0d52011-02-18 19:32:20 +00005378 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005379 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005380 if (!success)
5381 return false;
5382
5383 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005384 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005385 if (!success)
5386 return false;
5387
5388 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5389 uint32_t result = val1 & shifted;
5390
5391 EmulateInstruction::Context context;
5392 context.type = EmulateInstruction::eContextImmediate;
5393 context.SetNoArgs ();
5394
5395 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5396 return false;
5397 }
5398 return true;
5399}
5400
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005401// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5402// immediate value, and writes the result to the destination register. It can optionally update the
5403// condition flags based on the result.
5404bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005405EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005406{
5407#if 0
5408 // ARM pseudo code...
5409 if ConditionPassed() then
5410 EncodingSpecificOperations();
5411 result = R[n] AND NOT(imm32);
5412 if d == 15 then // Can only occur for ARM encoding
5413 ALUWritePC(result); // setflags is always FALSE here
5414 else
5415 R[d] = result;
5416 if setflags then
5417 APSR.N = result<31>;
5418 APSR.Z = IsZeroBit(result);
5419 APSR.C = carry;
5420 // APSR.V unchanged
5421#endif
5422
5423 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005424
Greg Clayton7bc39082011-03-24 23:53:38 +00005425 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005426 {
5427 uint32_t Rd, Rn;
5428 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5429 bool setflags;
5430 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5431 switch (encoding)
5432 {
5433 case eEncodingT1:
5434 Rd = Bits32(opcode, 11, 8);
5435 Rn = Bits32(opcode, 19, 16);
5436 setflags = BitIsSet(opcode, 20);
5437 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5438 if (BadReg(Rd) || BadReg(Rn))
5439 return false;
5440 break;
5441 case eEncodingA1:
5442 Rd = Bits32(opcode, 15, 12);
5443 Rn = Bits32(opcode, 19, 16);
5444 setflags = BitIsSet(opcode, 20);
5445 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005446 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005447 // TODO: Emulate SUBS PC, LR and related instructions.
5448 if (Rd == 15 && setflags)
5449 return false;
5450 break;
5451 default:
5452 return false;
5453 }
5454
5455 // Read the first operand.
5456 uint32_t val1 = ReadCoreReg(Rn, &success);
5457 if (!success)
5458 return false;
5459
5460 uint32_t result = val1 & ~imm32;
5461
5462 EmulateInstruction::Context context;
5463 context.type = EmulateInstruction::eContextImmediate;
5464 context.SetNoArgs ();
5465
5466 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5467 return false;
5468 }
5469 return true;
5470}
5471
5472// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5473// optionally-shifted register value, and writes the result to the destination register.
5474// It can optionally update the condition flags based on the result.
5475bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005476EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005477{
5478#if 0
5479 // ARM pseudo code...
5480 if ConditionPassed() then
5481 EncodingSpecificOperations();
5482 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5483 result = R[n] AND NOT(shifted);
5484 if d == 15 then // Can only occur for ARM encoding
5485 ALUWritePC(result); // setflags is always FALSE here
5486 else
5487 R[d] = result;
5488 if setflags then
5489 APSR.N = result<31>;
5490 APSR.Z = IsZeroBit(result);
5491 APSR.C = carry;
5492 // APSR.V unchanged
5493#endif
5494
5495 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005496
Greg Clayton7bc39082011-03-24 23:53:38 +00005497 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005498 {
5499 uint32_t Rd, Rn, Rm;
5500 ARM_ShifterType shift_t;
5501 uint32_t shift_n; // the shift applied to the value read from Rm
5502 bool setflags;
5503 uint32_t carry;
5504 switch (encoding)
5505 {
5506 case eEncodingT1:
5507 Rd = Rn = Bits32(opcode, 2, 0);
5508 Rm = Bits32(opcode, 5, 3);
5509 setflags = !InITBlock();
5510 shift_t = SRType_LSL;
5511 shift_n = 0;
5512 break;
5513 case eEncodingT2:
5514 Rd = Bits32(opcode, 11, 8);
5515 Rn = Bits32(opcode, 19, 16);
5516 Rm = Bits32(opcode, 3, 0);
5517 setflags = BitIsSet(opcode, 20);
5518 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5519 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5520 return false;
5521 break;
5522 case eEncodingA1:
5523 Rd = Bits32(opcode, 15, 12);
5524 Rn = Bits32(opcode, 19, 16);
5525 Rm = Bits32(opcode, 3, 0);
5526 setflags = BitIsSet(opcode, 20);
5527 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005528 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005529 // TODO: Emulate SUBS PC, LR and related instructions.
5530 if (Rd == 15 && setflags)
5531 return false;
5532 break;
5533 default:
5534 return false;
5535 }
5536
5537 // Read the first operand.
5538 uint32_t val1 = ReadCoreReg(Rn, &success);
5539 if (!success)
5540 return false;
5541
5542 // Read the second operand.
5543 uint32_t val2 = ReadCoreReg(Rm, &success);
5544 if (!success)
5545 return false;
5546
5547 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5548 uint32_t result = val1 & ~shifted;
5549
5550 EmulateInstruction::Context context;
5551 context.type = EmulateInstruction::eContextImmediate;
5552 context.SetNoArgs ();
5553
5554 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5555 return false;
5556 }
5557 return true;
5558}
5559
Caroline Tice4d729c52011-02-18 00:55:53 +00005560// 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 +00005561// 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 +00005562bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005563EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005564{
5565#if 0
5566 if ConditionPassed() then
5567 EncodingSpecificOperations();
5568 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5569 address = if index then offset_addr else R[n];
5570 data = MemU[address,4];
5571 if wback then R[n] = offset_addr;
5572 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005573 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5574 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005575 R[t] = data;
5576 else // Can only apply before ARMv7
5577 R[t] = ROR(data, 8*UInt(address<1:0>));
5578#endif
5579
5580 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005581
Greg Clayton7bc39082011-03-24 23:53:38 +00005582 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005583 {
5584 const uint32_t addr_byte_size = GetAddressByteSize();
5585
5586 uint32_t t;
5587 uint32_t n;
5588 uint32_t imm32;
5589 bool index;
5590 bool add;
5591 bool wback;
5592
5593 switch (encoding)
5594 {
5595 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005596 // if Rn == '1111' then SEE LDR (literal);
5597 // if P == '0' && W == '1' then SEE LDRT;
5598 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005599 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5600 t = Bits32 (opcode, 15, 12);
5601 n = Bits32 (opcode, 19, 16);
5602 imm32 = Bits32 (opcode, 11, 0);
5603
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005604 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5605 index = BitIsSet (opcode, 24);
5606 add = BitIsSet (opcode, 23);
5607 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005608
5609 // if wback && n == t then UNPREDICTABLE;
5610 if (wback && (n == t))
5611 return false;
5612
5613 break;
5614
5615 default:
5616 return false;
5617 }
5618
5619 addr_t address;
5620 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005621 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005622 if (!success)
5623 return false;
5624
5625 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5626 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005627 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005628 else
5629 offset_addr = base_address - imm32;
5630
5631 // address = if index then offset_addr else R[n];
5632 if (index)
5633 address = offset_addr;
5634 else
5635 address = base_address;
5636
5637 // data = MemU[address,4];
5638
5639 Register base_reg;
5640 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5641
5642 EmulateInstruction::Context context;
5643 context.type = eContextRegisterLoad;
5644 context.SetRegisterPlusOffset (base_reg, address - base_address);
5645
5646 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5647 if (!success)
5648 return false;
5649
5650 // if wback then R[n] = offset_addr;
5651 if (wback)
5652 {
5653 context.type = eContextAdjustBaseRegister;
5654 context.SetAddress (offset_addr);
5655 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5656 return false;
5657 }
5658
5659 // if t == 15 then
5660 if (t == 15)
5661 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005662 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005663 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5664 {
5665 // LoadWritePC (data);
5666 context.type = eContextRegisterLoad;
5667 context.SetRegisterPlusOffset (base_reg, address - base_address);
5668 LoadWritePC (context, data);
5669 }
5670 else
5671 return false;
5672 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005673 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005674 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5675 {
5676 // R[t] = data;
5677 context.type = eContextRegisterLoad;
5678 context.SetRegisterPlusOffset (base_reg, address - base_address);
5679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5680 return false;
5681 }
5682 // else // Can only apply before ARMv7
5683 else
5684 {
5685 // R[t] = ROR(data, 8*UInt(address<1:0>));
5686 data = ROR (data, Bits32 (address, 1, 0));
5687 context.type = eContextRegisterLoad;
5688 context.SetImmediate (data);
5689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5690 return false;
5691 }
5692
5693 }
5694 return true;
5695}
5696
Caroline Ticefe479112011-02-18 18:52:37 +00005697// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5698// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5699bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005700EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005701{
5702#if 0
5703 if ConditionPassed() then
5704 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5705 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5706 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5707 address = if index then offset_addr else R[n];
5708 data = MemU[address,4];
5709 if wback then R[n] = offset_addr;
5710 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005711 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5712 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005713 R[t] = data;
5714 else // Can only apply before ARMv7
5715 if CurrentInstrSet() == InstrSet_ARM then
5716 R[t] = ROR(data, 8*UInt(address<1:0>));
5717 else
5718 R[t] = bits(32) UNKNOWN;
5719#endif
5720
5721 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005722
Greg Clayton7bc39082011-03-24 23:53:38 +00005723 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005724 {
5725 const uint32_t addr_byte_size = GetAddressByteSize();
5726
5727 uint32_t t;
5728 uint32_t n;
5729 uint32_t m;
5730 bool index;
5731 bool add;
5732 bool wback;
5733 ARM_ShifterType shift_t;
5734 uint32_t shift_n;
5735
5736 switch (encoding)
5737 {
5738 case eEncodingT1:
5739 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5740 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5741 t = Bits32 (opcode, 2, 0);
5742 n = Bits32 (opcode, 5, 3);
5743 m = Bits32 (opcode, 8, 6);
5744
5745 // index = TRUE; add = TRUE; wback = FALSE;
5746 index = true;
5747 add = true;
5748 wback = false;
5749
5750 // (shift_t, shift_n) = (SRType_LSL, 0);
5751 shift_t = SRType_LSL;
5752 shift_n = 0;
5753
5754 break;
5755
5756 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005757 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005758 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5759 t = Bits32 (opcode, 15, 12);
5760 n = Bits32 (opcode, 19, 16);
5761 m = Bits32 (opcode, 3, 0);
5762
5763 // index = TRUE; add = TRUE; wback = FALSE;
5764 index = true;
5765 add = true;
5766 wback = false;
5767
5768 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5769 shift_t = SRType_LSL;
5770 shift_n = Bits32 (opcode, 5, 4);
5771
5772 // if BadReg(m) then UNPREDICTABLE;
5773 if (BadReg (m))
5774 return false;
5775
5776 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5777 if ((t == 15) && InITBlock() && !LastInITBlock())
5778 return false;
5779
5780 break;
5781
5782 case eEncodingA1:
5783 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005784 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005785 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5786 t = Bits32 (opcode, 15, 12);
5787 n = Bits32 (opcode, 19, 16);
5788 m = Bits32 (opcode, 3, 0);
5789
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005790 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005791 index = BitIsSet (opcode, 24);
5792 add = BitIsSet (opcode, 23);
5793 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5794
5795 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5796 uint32_t type = Bits32 (opcode, 6, 5);
5797 uint32_t imm5 = Bits32 (opcode, 11, 7);
5798 shift_n = DecodeImmShift (type, imm5, shift_t);
5799
5800 // if m == 15 then UNPREDICTABLE;
5801 if (m == 15)
5802 return false;
5803
5804 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5805 if (wback && ((n == 15) || (n == t)))
5806 return false;
5807 }
5808 break;
5809
5810
5811 default:
5812 return false;
5813 }
5814
5815 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5816 if (!success)
5817 return false;
5818
5819 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5820 if (!success)
5821 return false;
5822
5823 addr_t offset_addr;
5824 addr_t address;
5825
5826 // 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 +00005827 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005828
5829 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5830 if (add)
5831 offset_addr = Rn + offset;
5832 else
5833 offset_addr = Rn - offset;
5834
5835 // address = if index then offset_addr else R[n];
5836 if (index)
5837 address = offset_addr;
5838 else
5839 address = Rn;
5840
5841 // data = MemU[address,4];
5842 Register base_reg;
5843 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5844
5845 EmulateInstruction::Context context;
5846 context.type = eContextRegisterLoad;
5847 context.SetRegisterPlusOffset (base_reg, address - Rn);
5848
5849 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5850 if (!success)
5851 return false;
5852
5853 // if wback then R[n] = offset_addr;
5854 if (wback)
5855 {
5856 context.type = eContextAdjustBaseRegister;
5857 context.SetAddress (offset_addr);
5858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5859 return false;
5860 }
5861
5862 // if t == 15 then
5863 if (t == 15)
5864 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005865 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005866 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5867 {
5868 context.type = eContextRegisterLoad;
5869 context.SetRegisterPlusOffset (base_reg, address - Rn);
5870 LoadWritePC (context, data);
5871 }
5872 else
5873 return false;
5874 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005875 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005876 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5877 {
5878 // R[t] = data;
5879 context.type = eContextRegisterLoad;
5880 context.SetRegisterPlusOffset (base_reg, address - Rn);
5881 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5882 return false;
5883 }
5884 else // Can only apply before ARMv7
5885 {
5886 // if CurrentInstrSet() == InstrSet_ARM then
5887 if (CurrentInstrSet () == eModeARM)
5888 {
5889 // R[t] = ROR(data, 8*UInt(address<1:0>));
5890 data = ROR (data, Bits32 (address, 1, 0));
5891 context.type = eContextRegisterLoad;
5892 context.SetImmediate (data);
5893 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5894 return false;
5895 }
5896 else
5897 {
5898 // R[t] = bits(32) UNKNOWN;
5899 WriteBits32Unknown (t);
5900 }
5901 }
5902 }
5903 return true;
5904}
Caroline Tice21b604b2011-02-18 21:06:04 +00005905
5906// LDRB (immediate, Thumb)
5907bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005908EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005909{
5910#if 0
5911 if ConditionPassed() then
5912 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5913 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5914 address = if index then offset_addr else R[n];
5915 R[t] = ZeroExtend(MemU[address,1], 32);
5916 if wback then R[n] = offset_addr;
5917#endif
5918
5919 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005920
Greg Clayton7bc39082011-03-24 23:53:38 +00005921 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005922 {
5923 uint32_t t;
5924 uint32_t n;
5925 uint32_t imm32;
5926 bool index;
5927 bool add;
5928 bool wback;
5929
5930 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5931 switch (encoding)
5932 {
5933 case eEncodingT1:
5934 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5935 t = Bits32 (opcode, 2, 0);
5936 n = Bits32 (opcode, 5, 3);
5937 imm32 = Bits32 (opcode, 10, 6);
5938
5939 // index = TRUE; add = TRUE; wback = FALSE;
5940 index = true;
5941 add = true;
5942 wback= false;
5943
5944 break;
5945
5946 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005947 // if Rt == '1111' then SEE PLD;
5948 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00005949 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5950 t = Bits32 (opcode, 15, 12);
5951 n = Bits32 (opcode, 19, 16);
5952 imm32 = Bits32 (opcode, 11, 0);
5953
5954 // index = TRUE; add = TRUE; wback = FALSE;
5955 index = true;
5956 add = true;
5957 wback = false;
5958
5959 // if t == 13 then UNPREDICTABLE;
5960 if (t == 13)
5961 return false;
5962
5963 break;
5964
5965 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005966 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
5967 // if Rn == '1111' then SEE LDRB (literal);
5968 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
5969 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00005970 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5971 return false;
5972
5973 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5974 t = Bits32 (opcode, 15, 12);
5975 n = Bits32 (opcode, 19, 16);
5976 imm32 = Bits32 (opcode, 7, 0);
5977
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005978 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00005979 index = BitIsSet (opcode, 10);
5980 add = BitIsSet (opcode, 9);
5981 wback = BitIsSet (opcode, 8);
5982
5983 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5984 if (BadReg (t) || (wback && (n == t)))
5985 return false;
5986
5987 break;
5988
5989 default:
5990 return false;
5991 }
5992
5993 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5994 if (!success)
5995 return false;
5996
5997 addr_t address;
5998 addr_t offset_addr;
5999
6000 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6001 if (add)
6002 offset_addr = Rn + imm32;
6003 else
6004 offset_addr = Rn - imm32;
6005
6006 // address = if index then offset_addr else R[n];
6007 if (index)
6008 address = offset_addr;
6009 else
6010 address = Rn;
6011
6012 // R[t] = ZeroExtend(MemU[address,1], 32);
6013 Register base_reg;
6014 Register data_reg;
6015 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6016 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6017
6018 EmulateInstruction::Context context;
6019 context.type = eContextRegisterLoad;
6020 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6021
6022 uint64_t data = MemURead (context, address, 1, 0, &success);
6023 if (!success)
6024 return false;
6025
6026 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6027 return false;
6028
6029 // if wback then R[n] = offset_addr;
6030 if (wback)
6031 {
6032 context.type = eContextAdjustBaseRegister;
6033 context.SetAddress (offset_addr);
6034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6035 return false;
6036 }
6037 }
6038 return true;
6039}
Caroline Ticef55261f2011-02-18 22:24:22 +00006040
6041// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6042// zero-extends it to form a 32-bit word and writes it to a register.
6043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006044EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006045{
6046#if 0
6047 if ConditionPassed() then
6048 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6049 base = Align(PC,4);
6050 address = if add then (base + imm32) else (base - imm32);
6051 R[t] = ZeroExtend(MemU[address,1], 32);
6052#endif
6053
6054 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006055
Greg Clayton7bc39082011-03-24 23:53:38 +00006056 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006057 {
6058 uint32_t t;
6059 uint32_t imm32;
6060 bool add;
6061 switch (encoding)
6062 {
6063 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006064 // if Rt == '1111' then SEE PLD;
6065 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006066 t = Bits32 (opcode, 15, 12);
6067 imm32 = Bits32 (opcode, 11, 0);
6068 add = BitIsSet (opcode, 23);
6069
6070 // if t == 13 then UNPREDICTABLE;
6071 if (t == 13)
6072 return false;
6073
6074 break;
6075
6076 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006077 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006078 t = Bits32 (opcode, 15, 12);
6079 imm32 = Bits32 (opcode, 11, 0);
6080 add = BitIsSet (opcode, 23);
6081
6082 // if t == 15 then UNPREDICTABLE;
6083 if (t == 15)
6084 return false;
6085 break;
6086
6087 default:
6088 return false;
6089 }
6090
6091 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006092 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006093 if (!success)
6094 return false;
6095
6096 uint32_t base = AlignPC (pc_val);
6097
6098 addr_t address;
6099 // address = if add then (base + imm32) else (base - imm32);
6100 if (add)
6101 address = base + imm32;
6102 else
6103 address = base - imm32;
6104
6105 // R[t] = ZeroExtend(MemU[address,1], 32);
6106 EmulateInstruction::Context context;
6107 context.type = eContextRelativeBranchImmediate;
6108 context.SetImmediate (address - base);
6109
6110 uint64_t data = MemURead (context, address, 1, 0, &success);
6111 if (!success)
6112 return false;
6113
6114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6115 return false;
6116 }
6117 return true;
6118}
Caroline Tice30fec122011-02-18 23:52:21 +00006119
6120// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6121// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6122// optionally be shifted.
6123bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006124EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006125{
6126#if 0
6127 if ConditionPassed() then
6128 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6129 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6130 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6131 address = if index then offset_addr else R[n];
6132 R[t] = ZeroExtend(MemU[address,1],32);
6133 if wback then R[n] = offset_addr;
6134#endif
6135
6136 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006137
Greg Clayton7bc39082011-03-24 23:53:38 +00006138 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006139 {
6140 uint32_t t;
6141 uint32_t n;
6142 uint32_t m;
6143 bool index;
6144 bool add;
6145 bool wback;
6146 ARM_ShifterType shift_t;
6147 uint32_t shift_n;
6148
6149 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6150 switch (encoding)
6151 {
6152 case eEncodingT1:
6153 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6154 t = Bits32 (opcode, 2, 0);
6155 n = Bits32 (opcode, 5, 3);
6156 m = Bits32 (opcode, 8, 6);
6157
6158 // index = TRUE; add = TRUE; wback = FALSE;
6159 index = true;
6160 add = true;
6161 wback = false;
6162
6163 // (shift_t, shift_n) = (SRType_LSL, 0);
6164 shift_t = SRType_LSL;
6165 shift_n = 0;
6166 break;
6167
6168 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006169 // if Rt == '1111' then SEE PLD;
6170 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006171 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6172 t = Bits32 (opcode, 15, 12);
6173 n = Bits32 (opcode, 19, 16);
6174 m = Bits32 (opcode, 3, 0);
6175
6176 // index = TRUE; add = TRUE; wback = FALSE;
6177 index = true;
6178 add = true;
6179 wback = false;
6180
6181 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6182 shift_t = SRType_LSL;
6183 shift_n = Bits32 (opcode, 5, 4);
6184
6185 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6186 if ((t == 13) || BadReg (m))
6187 return false;
6188 break;
6189
6190 case eEncodingA1:
6191 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006192 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6194 t = Bits32 (opcode, 15, 12);
6195 n = Bits32 (opcode, 19, 16);
6196 m = Bits32 (opcode, 3, 0);
6197
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006198 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006199 index = BitIsSet (opcode, 24);
6200 add = BitIsSet (opcode, 23);
6201 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6202
6203 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6204 uint32_t type = Bits32 (opcode, 6, 5);
6205 uint32_t imm5 = Bits32 (opcode, 11, 7);
6206 shift_n = DecodeImmShift (type, imm5, shift_t);
6207
6208 // if t == 15 || m == 15 then UNPREDICTABLE;
6209 if ((t == 15) || (m == 15))
6210 return false;
6211
6212 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6213 if (wback && ((n == 15) || (n == t)))
6214 return false;
6215 }
6216 break;
6217
6218 default:
6219 return false;
6220 }
6221
6222 addr_t offset_addr;
6223 addr_t address;
6224
6225 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6226 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6227 if (!success)
6228 return false;
6229
6230 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6231
6232 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6233 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6234 if (!success)
6235 return false;
6236
6237 if (add)
6238 offset_addr = Rn + offset;
6239 else
6240 offset_addr = Rn - offset;
6241
6242 // address = if index then offset_addr else R[n];
6243 if (index)
6244 address = offset_addr;
6245 else
6246 address = Rn;
6247
6248 // R[t] = ZeroExtend(MemU[address,1],32);
6249 Register base_reg;
6250 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6251
6252 EmulateInstruction::Context context;
6253 context.type = eContextRegisterLoad;
6254 context.SetRegisterPlusOffset (base_reg, address - Rn);
6255
6256 uint64_t data = MemURead (context, address, 1, 0, &success);
6257 if (!success)
6258 return false;
6259
6260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6261 return false;
6262
6263 // if wback then R[n] = offset_addr;
6264 if (wback)
6265 {
6266 context.type = eContextAdjustBaseRegister;
6267 context.SetAddress (offset_addr);
6268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6269 return false;
6270 }
6271 }
6272 return true;
6273}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006274
6275// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6276// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6277// post-indexed, or pre-indexed addressing.
6278bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006279EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006280{
6281#if 0
6282 if ConditionPassed() then
6283 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6284 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6285 address = if index then offset_addr else R[n];
6286 data = MemU[address,2];
6287 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006288 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006289 R[t] = ZeroExtend(data, 32);
6290 else // Can only apply before ARMv7
6291 R[t] = bits(32) UNKNOWN;
6292#endif
6293
6294
6295 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006296
Greg Clayton7bc39082011-03-24 23:53:38 +00006297 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006298 {
6299 uint32_t t;
6300 uint32_t n;
6301 uint32_t imm32;
6302 bool index;
6303 bool add;
6304 bool wback;
6305
6306 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6307 switch (encoding)
6308 {
6309 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006310 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006311 t = Bits32 (opcode, 2, 0);
6312 n = Bits32 (opcode, 5, 3);
6313 imm32 = Bits32 (opcode, 10, 6) << 1;
6314
6315 // index = TRUE; add = TRUE; wback = FALSE;
6316 index = true;
6317 add = true;
6318 wback = false;
6319
6320 break;
6321
6322 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006323 // if Rt == '1111' then SEE "Unallocated memory hints";
6324 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006325 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6326 t = Bits32 (opcode, 15, 12);
6327 n = Bits32 (opcode, 19, 16);
6328 imm32 = Bits32 (opcode, 11, 0);
6329
6330 // index = TRUE; add = TRUE; wback = FALSE;
6331 index = true;
6332 add = true;
6333 wback = false;
6334
6335 // if t == 13 then UNPREDICTABLE;
6336 if (t == 13)
6337 return false;
6338 break;
6339
6340 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006341 // if Rn == '1111' then SEE LDRH (literal);
6342 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6343 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6344 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006345 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6346 return false;
6347
6348 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6349 t = Bits32 (opcode, 15, 12);
6350 n = Bits32 (opcode, 19, 16);
6351 imm32 = Bits32 (opcode, 7, 0);
6352
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006353 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006354 index = BitIsSet (opcode, 10);
6355 add = BitIsSet (opcode, 9);
6356 wback = BitIsSet (opcode, 8);
6357
6358 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6359 if (BadReg (t) || (wback && (n == t)))
6360 return false;
6361 break;
6362
6363 default:
6364 return false;
6365 }
6366
6367 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6368 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6369 if (!success)
6370 return false;
6371
6372 addr_t offset_addr;
6373 addr_t address;
6374
6375 if (add)
6376 offset_addr = Rn + imm32;
6377 else
6378 offset_addr = Rn - imm32;
6379
6380 // address = if index then offset_addr else R[n];
6381 if (index)
6382 address = offset_addr;
6383 else
6384 address = Rn;
6385
6386 // data = MemU[address,2];
6387 Register base_reg;
6388 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6389
6390 EmulateInstruction::Context context;
6391 context.type = eContextRegisterLoad;
6392 context.SetRegisterPlusOffset (base_reg, address - Rn);
6393
6394 uint64_t data = MemURead (context, address, 2, 0, &success);
6395 if (!success)
6396 return false;
6397
6398 // if wback then R[n] = offset_addr;
6399 if (wback)
6400 {
6401 context.type = eContextAdjustBaseRegister;
6402 context.SetAddress (offset_addr);
6403 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6404 return false;
6405 }
6406
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006407 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006408 if (UnalignedSupport () || BitIsClear (address, 0))
6409 {
6410 // R[t] = ZeroExtend(data, 32);
6411 context.type = eContextRegisterLoad;
6412 context.SetRegisterPlusOffset (base_reg, address - Rn);
6413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6414 return false;
6415 }
6416 else // Can only apply before ARMv7
6417 {
6418 // R[t] = bits(32) UNKNOWN;
6419 WriteBits32Unknown (t);
6420 }
6421 }
6422 return true;
6423}
Caroline Ticefe479112011-02-18 18:52:37 +00006424
Caroline Tice952b5382011-02-28 23:15:24 +00006425// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6426// zero-extends it to form a 32-bit word, and writes it to a register.
6427bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006428EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006429{
6430#if 0
6431 if ConditionPassed() then
6432 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6433 base = Align(PC,4);
6434 address = if add then (base + imm32) else (base - imm32);
6435 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006436 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006437 R[t] = ZeroExtend(data, 32);
6438 else // Can only apply before ARMv7
6439 R[t] = bits(32) UNKNOWN;
6440#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006441
Caroline Tice952b5382011-02-28 23:15:24 +00006442 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006443
Greg Clayton7bc39082011-03-24 23:53:38 +00006444 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006445 {
6446 uint32_t t;
6447 uint32_t imm32;
6448 bool add;
6449
6450 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6451 switch (encoding)
6452 {
6453 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006454 // if Rt == '1111' then SEE "Unallocated memory hints";
6455 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006456 t = Bits32 (opcode, 15, 12);
6457 imm32 = Bits32 (opcode, 11, 0);
6458 add = BitIsSet (opcode, 23);
6459
6460 // if t == 13 then UNPREDICTABLE;
6461 if (t == 13)
6462 return false;
6463
6464 break;
6465
6466 case eEncodingA1:
6467 {
6468 uint32_t imm4H = Bits32 (opcode, 11, 8);
6469 uint32_t imm4L = Bits32 (opcode, 3, 0);
6470
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006471 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006472 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006473 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006474 add = BitIsSet (opcode, 23);
6475
6476 // if t == 15 then UNPREDICTABLE;
6477 if (t == 15)
6478 return false;
6479 break;
6480 }
6481
6482 default:
6483 return false;
6484 }
6485
6486 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006487 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006488 if (!success)
6489 return false;
6490
6491 addr_t base = AlignPC (pc_value);
6492 addr_t address;
6493
6494 // address = if add then (base + imm32) else (base - imm32);
6495 if (add)
6496 address = base + imm32;
6497 else
6498 address = base - imm32;
6499
6500 // data = MemU[address,2];
6501 Register base_reg;
6502 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6503
6504 EmulateInstruction::Context context;
6505 context.type = eContextRegisterLoad;
6506 context.SetRegisterPlusOffset (base_reg, address - base);
6507
6508 uint64_t data = MemURead (context, address, 2, 0, &success);
6509 if (!success)
6510 return false;
6511
6512
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006513 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006514 if (UnalignedSupport () || BitIsClear (address, 0))
6515 {
6516 // R[t] = ZeroExtend(data, 32);
6517 context.type = eContextRegisterLoad;
6518 context.SetRegisterPlusOffset (base_reg, address - base);
6519 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6520 return false;
6521
6522 }
6523 else // Can only apply before ARMv7
6524 {
6525 // R[t] = bits(32) UNKNOWN;
6526 WriteBits32Unknown (t);
6527 }
6528 }
6529 return true;
6530}
6531
Caroline Tice0e6bc952011-03-01 18:00:42 +00006532// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6533// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6534// be shifted left by 0, 1, 2, or 3 bits.
6535bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006536EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006537{
6538#if 0
6539 if ConditionPassed() then
6540 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6541 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6542 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6543 address = if index then offset_addr else R[n];
6544 data = MemU[address,2];
6545 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006546 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006547 R[t] = ZeroExtend(data, 32);
6548 else // Can only apply before ARMv7
6549 R[t] = bits(32) UNKNOWN;
6550#endif
6551
6552 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006553
Greg Clayton7bc39082011-03-24 23:53:38 +00006554 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006555 {
6556 uint32_t t;
6557 uint32_t n;
6558 uint32_t m;
6559 bool index;
6560 bool add;
6561 bool wback;
6562 ARM_ShifterType shift_t;
6563 uint32_t shift_n;
6564
6565 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6566 switch (encoding)
6567 {
6568 case eEncodingT1:
6569 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6570 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6571 t = Bits32 (opcode, 2, 0);
6572 n = Bits32 (opcode, 5, 3);
6573 m = Bits32 (opcode, 8, 6);
6574
6575 // index = TRUE; add = TRUE; wback = FALSE;
6576 index = true;
6577 add = true;
6578 wback = false;
6579
6580 // (shift_t, shift_n) = (SRType_LSL, 0);
6581 shift_t = SRType_LSL;
6582 shift_n = 0;
6583
6584 break;
6585
6586 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006587 // if Rn == '1111' then SEE LDRH (literal);
6588 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006589 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6590 t = Bits32 (opcode, 15, 12);
6591 n = Bits32 (opcode, 19, 16);
6592 m = Bits32 (opcode, 3, 0);
6593
6594 // index = TRUE; add = TRUE; wback = FALSE;
6595 index = true;
6596 add = true;
6597 wback = false;
6598
6599 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6600 shift_t = SRType_LSL;
6601 shift_n = Bits32 (opcode, 5, 4);
6602
6603 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6604 if ((t == 13) || BadReg (m))
6605 return false;
6606 break;
6607
6608 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006609 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006610 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6611 t = Bits32 (opcode, 15, 12);
6612 n = Bits32 (opcode, 19, 16);
6613 m = Bits32 (opcode, 3, 0);
6614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006615 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006616 index = BitIsSet (opcode, 24);
6617 add = BitIsSet (opcode, 23);
6618 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6619
6620 // (shift_t, shift_n) = (SRType_LSL, 0);
6621 shift_t = SRType_LSL;
6622 shift_n = 0;
6623
6624 // if t == 15 || m == 15 then UNPREDICTABLE;
6625 if ((t == 15) || (m == 15))
6626 return false;
6627
6628 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6629 if (wback && ((n == 15) || (n == t)))
6630 return false;
6631
6632 break;
6633
6634 default:
6635 return false;
6636 }
6637
6638 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6639
6640 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6641 if (!success)
6642 return false;
6643
6644 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6645
6646 addr_t offset_addr;
6647 addr_t address;
6648
6649 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6650 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6651 if (!success)
6652 return false;
6653
6654 if (add)
6655 offset_addr = Rn + offset;
6656 else
6657 offset_addr = Rn - offset;
6658
6659 // address = if index then offset_addr else R[n];
6660 if (index)
6661 address = offset_addr;
6662 else
6663 address = Rn;
6664
6665 // data = MemU[address,2];
6666 Register base_reg;
6667 Register offset_reg;
6668 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6669 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6670
6671 EmulateInstruction::Context context;
6672 context.type = eContextRegisterLoad;
6673 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6674 uint64_t data = MemURead (context, address, 2, 0, &success);
6675 if (!success)
6676 return false;
6677
6678 // if wback then R[n] = offset_addr;
6679 if (wback)
6680 {
6681 context.type = eContextAdjustBaseRegister;
6682 context.SetAddress (offset_addr);
6683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6684 return false;
6685 }
6686
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006687 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006688 if (UnalignedSupport() || BitIsClear (address, 0))
6689 {
6690 // R[t] = ZeroExtend(data, 32);
6691 context.type = eContextRegisterLoad;
6692 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6693 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6694 return false;
6695 }
6696 else // Can only apply before ARMv7
6697 {
6698 // R[t] = bits(32) UNKNOWN;
6699 WriteBits32Unknown (t);
6700 }
6701 }
6702 return true;
6703}
6704
Caroline Ticea5e28af2011-03-01 21:53:03 +00006705// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6706// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6707// or pre-indexed addressing.
6708bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006709EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006710{
6711#if 0
6712 if ConditionPassed() then
6713 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6714 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6715 address = if index then offset_addr else R[n];
6716 R[t] = SignExtend(MemU[address,1], 32);
6717 if wback then R[n] = offset_addr;
6718#endif
6719
6720 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006721
Greg Clayton7bc39082011-03-24 23:53:38 +00006722 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006723 {
6724 uint32_t t;
6725 uint32_t n;
6726 uint32_t imm32;
6727 bool index;
6728 bool add;
6729 bool wback;
6730
6731 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6732 switch (encoding)
6733 {
6734 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006735 // if Rt == '1111' then SEE PLI;
6736 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006737 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6738 t = Bits32 (opcode, 15, 12);
6739 n = Bits32 (opcode, 19, 16);
6740 imm32 = Bits32 (opcode, 11, 0);
6741
6742 // index = TRUE; add = TRUE; wback = FALSE;
6743 index = true;
6744 add = true;
6745 wback = false;
6746
6747 // if t == 13 then UNPREDICTABLE;
6748 if (t == 13)
6749 return false;
6750
6751 break;
6752
6753 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006754 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6755 // if Rn == '1111' then SEE LDRSB (literal);
6756 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6757 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006758 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6759 return false;
6760
6761 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6762 t = Bits32 (opcode, 15, 12);
6763 n = Bits32 (opcode, 19, 16);
6764 imm32 = Bits32 (opcode, 7, 0);
6765
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006766 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006767 index = BitIsSet (opcode, 10);
6768 add = BitIsSet (opcode, 9);
6769 wback = BitIsSet (opcode, 8);
6770
6771 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006772 if (((t == 13) || ((t == 15)
6773 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6774 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006775 return false;
6776
6777 break;
6778
6779 case eEncodingA1:
6780 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006781 // if Rn == '1111' then SEE LDRSB (literal);
6782 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006783 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6784 t = Bits32 (opcode, 15, 12);
6785 n = Bits32 (opcode, 19, 16);
6786
6787 uint32_t imm4H = Bits32 (opcode, 11, 8);
6788 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006789 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006790
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006791 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006792 index = BitIsSet (opcode, 24);
6793 add = BitIsSet (opcode, 23);
6794 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6795
6796 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6797 if ((t == 15) || (wback && (n == t)))
6798 return false;
6799
6800 break;
6801 }
6802
6803 default:
6804 return false;
6805 }
6806
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006807 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006808 if (!success)
6809 return false;
6810
6811 addr_t offset_addr;
6812 addr_t address;
6813
6814 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6815 if (add)
6816 offset_addr = Rn + imm32;
6817 else
6818 offset_addr = Rn - imm32;
6819
6820 // address = if index then offset_addr else R[n];
6821 if (index)
6822 address = offset_addr;
6823 else
6824 address = Rn;
6825
6826 // R[t] = SignExtend(MemU[address,1], 32);
6827 Register base_reg;
6828 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6829
6830 EmulateInstruction::Context context;
6831 context.type = eContextRegisterLoad;
6832 context.SetRegisterPlusOffset (base_reg, address - Rn);
6833
6834 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6835 if (!success)
6836 return false;
6837
6838 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6839 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6840 return false;
6841
6842 // if wback then R[n] = offset_addr;
6843 if (wback)
6844 {
6845 context.type = eContextAdjustBaseRegister;
6846 context.SetAddress (offset_addr);
6847 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6848 return false;
6849 }
6850 }
6851
6852 return true;
6853}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006854
Caroline Tice5f593912011-03-01 22:25:17 +00006855// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6856// sign-extends it to form a 32-bit word, and writes tit to a register.
6857bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006858EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006859{
6860#if 0
6861 if ConditionPassed() then
6862 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6863 base = Align(PC,4);
6864 address = if add then (base + imm32) else (base - imm32);
6865 R[t] = SignExtend(MemU[address,1], 32);
6866#endif
6867
6868 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006869
Greg Clayton7bc39082011-03-24 23:53:38 +00006870 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006871 {
6872 uint32_t t;
6873 uint32_t imm32;
6874 bool add;
6875
6876 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6877 switch (encoding)
6878 {
6879 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006880 // if Rt == '1111' then SEE PLI;
6881 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006882 t = Bits32 (opcode, 15, 12);
6883 imm32 = Bits32 (opcode, 11, 0);
6884 add = BitIsSet (opcode, 23);
6885
6886 // if t == 13 then UNPREDICTABLE;
6887 if (t == 13)
6888 return false;
6889
6890 break;
6891
6892 case eEncodingA1:
6893 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006894 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006895 t = Bits32 (opcode, 15, 12);
6896 uint32_t imm4H = Bits32 (opcode, 11, 8);
6897 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006898 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006899 add = BitIsSet (opcode, 23);
6900
6901 // if t == 15 then UNPREDICTABLE;
6902 if (t == 15)
6903 return false;
6904
6905 break;
6906 }
6907
6908 default:
6909 return false;
6910 }
6911
6912 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006913 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006914 if (!success)
6915 return false;
6916 uint64_t base = AlignPC (pc_value);
6917
6918 // address = if add then (base + imm32) else (base - imm32);
6919 addr_t address;
6920 if (add)
6921 address = base + imm32;
6922 else
6923 address = base - imm32;
6924
6925 // R[t] = SignExtend(MemU[address,1], 32);
6926 Register base_reg;
6927 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6928
6929 EmulateInstruction::Context context;
6930 context.type = eContextRegisterLoad;
6931 context.SetRegisterPlusOffset (base_reg, address - base);
6932
6933 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6934 if (!success)
6935 return false;
6936
6937 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6938 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6939 return false;
6940 }
6941 return true;
6942}
6943
Caroline Tice672f3112011-03-01 23:55:59 +00006944// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6945// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6946// shifted left by 0, 1, 2, or 3 bits.
6947bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006948EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00006949{
6950#if 0
6951 if ConditionPassed() then
6952 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6953 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6954 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6955 address = if index then offset_addr else R[n];
6956 R[t] = SignExtend(MemU[address,1], 32);
6957 if wback then R[n] = offset_addr;
6958#endif
6959
6960 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00006961
Greg Clayton7bc39082011-03-24 23:53:38 +00006962 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00006963 {
6964 uint32_t t;
6965 uint32_t n;
6966 uint32_t m;
6967 bool index;
6968 bool add;
6969 bool wback;
6970 ARM_ShifterType shift_t;
6971 uint32_t shift_n;
6972
6973 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6974 switch (encoding)
6975 {
6976 case eEncodingT1:
6977 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6978 t = Bits32 (opcode, 2, 0);
6979 n = Bits32 (opcode, 5, 3);
6980 m = Bits32 (opcode, 8, 6);
6981
6982 // index = TRUE; add = TRUE; wback = FALSE;
6983 index = true;
6984 add = true;
6985 wback = false;
6986
6987 // (shift_t, shift_n) = (SRType_LSL, 0);
6988 shift_t = SRType_LSL;
6989 shift_n = 0;
6990
6991 break;
6992
6993 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006994 // if Rt == '1111' then SEE PLI;
6995 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00006996 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6997 t = Bits32 (opcode, 15, 12);
6998 n = Bits32 (opcode, 19, 16);
6999 m = Bits32 (opcode, 3, 0);
7000
7001 // index = TRUE; add = TRUE; wback = FALSE;
7002 index = true;
7003 add = true;
7004 wback = false;
7005
7006 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7007 shift_t = SRType_LSL;
7008 shift_n = Bits32 (opcode, 5, 4);
7009
7010 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7011 if ((t == 13) || BadReg (m))
7012 return false;
7013 break;
7014
7015 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007016 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007017 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7018 t = Bits32 (opcode, 15, 12);
7019 n = Bits32 (opcode, 19, 16);
7020 m = Bits32 (opcode, 3, 0);
7021
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007022 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007023 index = BitIsSet (opcode, 24);
7024 add = BitIsSet (opcode, 23);
7025 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7026
7027 // (shift_t, shift_n) = (SRType_LSL, 0);
7028 shift_t = SRType_LSL;
7029 shift_n = 0;
7030
7031 // if t == 15 || m == 15 then UNPREDICTABLE;
7032 if ((t == 15) || (m == 15))
7033 return false;
7034
7035 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7036 if (wback && ((n == 15) || (n == t)))
7037 return false;
7038 break;
7039
7040 default:
7041 return false;
7042 }
7043
7044 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7045 if (!success)
7046 return false;
7047
7048 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7049 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7050
7051 addr_t offset_addr;
7052 addr_t address;
7053
7054 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7055 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7056 if (!success)
7057 return false;
7058
7059 if (add)
7060 offset_addr = Rn + offset;
7061 else
7062 offset_addr = Rn - offset;
7063
7064 // address = if index then offset_addr else R[n];
7065 if (index)
7066 address = offset_addr;
7067 else
7068 address = Rn;
7069
7070 // R[t] = SignExtend(MemU[address,1], 32);
7071 Register base_reg;
7072 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7073 Register offset_reg;
7074 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7075
7076 EmulateInstruction::Context context;
7077 context.type = eContextRegisterLoad;
7078 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7079
7080 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7081 if (!success)
7082 return false;
7083
7084 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7086 return false;
7087
7088 // if wback then R[n] = offset_addr;
7089 if (wback)
7090 {
7091 context.type = eContextAdjustBaseRegister;
7092 context.SetAddress (offset_addr);
7093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7094 return false;
7095 }
7096 }
7097 return true;
7098}
7099
Caroline Tice78fb5632011-03-02 00:39:42 +00007100// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7101// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7102// pre-indexed addressing.
7103bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007104EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007105{
7106#if 0
7107 if ConditionPassed() then
7108 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7109 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7110 address = if index then offset_addr else R[n];
7111 data = MemU[address,2];
7112 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007113 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007114 R[t] = SignExtend(data, 32);
7115 else // Can only apply before ARMv7
7116 R[t] = bits(32) UNKNOWN;
7117#endif
7118
7119 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007120
Greg Clayton7bc39082011-03-24 23:53:38 +00007121 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007122 {
7123 uint32_t t;
7124 uint32_t n;
7125 uint32_t imm32;
7126 bool index;
7127 bool add;
7128 bool wback;
7129
7130 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7131 switch (encoding)
7132 {
7133 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007134 // if Rn == '1111' then SEE LDRSH (literal);
7135 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007136 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7137 t = Bits32 (opcode, 15, 12);
7138 n = Bits32 (opcode, 19, 16);
7139 imm32 = Bits32 (opcode, 11, 0);
7140
7141 // index = TRUE; add = TRUE; wback = FALSE;
7142 index = true;
7143 add = true;
7144 wback = false;
7145
7146 // if t == 13 then UNPREDICTABLE;
7147 if (t == 13)
7148 return false;
7149
7150 break;
7151
7152 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007153 // if Rn == '1111' then SEE LDRSH (literal);
7154 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7155 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7156 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007157 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7158 return false;
7159
7160 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7161 t = Bits32 (opcode, 15, 12);
7162 n = Bits32 (opcode, 19, 16);
7163 imm32 = Bits32 (opcode, 7, 0);
7164
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007165 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007166 index = BitIsSet (opcode, 10);
7167 add = BitIsSet (opcode, 9);
7168 wback = BitIsSet (opcode, 8);
7169
7170 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7171 if (BadReg (t) || (wback && (n == t)))
7172 return false;
7173
7174 break;
7175
7176 case eEncodingA1:
7177 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007178 // if Rn == '1111' then SEE LDRSH (literal);
7179 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007180 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7181 t = Bits32 (opcode, 15, 12);
7182 n = Bits32 (opcode, 19, 16);
7183 uint32_t imm4H = Bits32 (opcode, 11,8);
7184 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007185 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007186
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007187 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007188 index = BitIsSet (opcode, 24);
7189 add = BitIsSet (opcode, 23);
7190 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7191
7192 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7193 if ((t == 15) || (wback && (n == t)))
7194 return false;
7195
7196 break;
7197 }
7198
7199 default:
7200 return false;
7201 }
7202
7203 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7204 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7205 if (!success)
7206 return false;
7207
7208 addr_t offset_addr;
7209 if (add)
7210 offset_addr = Rn + imm32;
7211 else
7212 offset_addr = Rn - imm32;
7213
7214 // address = if index then offset_addr else R[n];
7215 addr_t address;
7216 if (index)
7217 address = offset_addr;
7218 else
7219 address = Rn;
7220
7221 // data = MemU[address,2];
7222 Register base_reg;
7223 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7224
7225 EmulateInstruction::Context context;
7226 context.type = eContextRegisterLoad;
7227 context.SetRegisterPlusOffset (base_reg, address - Rn);
7228
7229 uint64_t data = MemURead (context, address, 2, 0, &success);
7230 if (!success)
7231 return false;
7232
7233 // if wback then R[n] = offset_addr;
7234 if (wback)
7235 {
7236 context.type = eContextAdjustBaseRegister;
7237 context.SetAddress (offset_addr);
7238 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7239 return false;
7240 }
7241
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007242 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007243 if (UnalignedSupport() || BitIsClear (address, 0))
7244 {
7245 // R[t] = SignExtend(data, 32);
7246 int64_t signed_data = llvm::SignExtend64<16>(data);
7247 context.type = eContextRegisterLoad;
7248 context.SetRegisterPlusOffset (base_reg, address - Rn);
7249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7250 return false;
7251 }
7252 else // Can only apply before ARMv7
7253 {
7254 // R[t] = bits(32) UNKNOWN;
7255 WriteBits32Unknown (t);
7256 }
7257 }
7258 return true;
7259}
7260
Caroline Ticed2fac092011-03-02 19:45:34 +00007261// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7262// sign-extends it to from a 32-bit word, and writes it to a register.
7263bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007264EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007265{
7266#if 0
7267 if ConditionPassed() then
7268 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7269 base = Align(PC,4);
7270 address = if add then (base + imm32) else (base - imm32);
7271 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007272 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007273 R[t] = SignExtend(data, 32);
7274 else // Can only apply before ARMv7
7275 R[t] = bits(32) UNKNOWN;
7276#endif
7277
7278 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007279
Greg Clayton7bc39082011-03-24 23:53:38 +00007280 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007281 {
7282 uint32_t t;
7283 uint32_t imm32;
7284 bool add;
7285
7286 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7287 switch (encoding)
7288 {
7289 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007290 // if Rt == '1111' then SEE "Unallocated memory hints";
7291 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007292 t = Bits32 (opcode, 15, 12);
7293 imm32 = Bits32 (opcode, 11, 0);
7294 add = BitIsSet (opcode, 23);
7295
7296 // if t == 13 then UNPREDICTABLE;
7297 if (t == 13)
7298 return false;
7299
7300 break;
7301
7302 case eEncodingA1:
7303 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007304 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007305 t = Bits32 (opcode, 15, 12);
7306 uint32_t imm4H = Bits32 (opcode, 11, 8);
7307 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007308 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007309 add = BitIsSet (opcode, 23);
7310
7311 // if t == 15 then UNPREDICTABLE;
7312 if (t == 15)
7313 return false;
7314
7315 break;
7316 }
7317 default:
7318 return false;
7319 }
7320
7321 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007322 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007323 if (!success)
7324 return false;
7325
7326 uint64_t base = AlignPC (pc_value);
7327
7328 addr_t address;
7329 // address = if add then (base + imm32) else (base - imm32);
7330 if (add)
7331 address = base + imm32;
7332 else
7333 address = base - imm32;
7334
7335 // data = MemU[address,2];
7336 Register base_reg;
7337 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7338
7339 EmulateInstruction::Context context;
7340 context.type = eContextRegisterLoad;
7341 context.SetRegisterPlusOffset (base_reg, imm32);
7342
7343 uint64_t data = MemURead (context, address, 2, 0, &success);
7344 if (!success)
7345 return false;
7346
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007347 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007348 if (UnalignedSupport() || BitIsClear (address, 0))
7349 {
7350 // R[t] = SignExtend(data, 32);
7351 int64_t signed_data = llvm::SignExtend64<16>(data);
7352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7353 return false;
7354 }
7355 else // Can only apply before ARMv7
7356 {
7357 // R[t] = bits(32) UNKNOWN;
7358 WriteBits32Unknown (t);
7359 }
7360 }
7361 return true;
7362}
7363
Caroline Tice291a3e92011-03-02 21:13:44 +00007364// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7365// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7366// shifted left by 0, 1, 2, or 3 bits.
7367bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007368EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007369{
7370#if 0
7371 if ConditionPassed() then
7372 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7373 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7374 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7375 address = if index then offset_addr else R[n];
7376 data = MemU[address,2];
7377 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007378 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007379 R[t] = SignExtend(data, 32);
7380 else // Can only apply before ARMv7
7381 R[t] = bits(32) UNKNOWN;
7382#endif
7383
7384 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007385
Greg Clayton7bc39082011-03-24 23:53:38 +00007386 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007387 {
7388 uint32_t t;
7389 uint32_t n;
7390 uint32_t m;
7391 bool index;
7392 bool add;
7393 bool wback;
7394 ARM_ShifterType shift_t;
7395 uint32_t shift_n;
7396
7397 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7398 switch (encoding)
7399 {
7400 case eEncodingT1:
7401 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7402 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7403 t = Bits32 (opcode, 2, 0);
7404 n = Bits32 (opcode, 5, 3);
7405 m = Bits32 (opcode, 8, 6);
7406
7407 // index = TRUE; add = TRUE; wback = FALSE;
7408 index = true;
7409 add = true;
7410 wback = false;
7411
7412 // (shift_t, shift_n) = (SRType_LSL, 0);
7413 shift_t = SRType_LSL;
7414 shift_n = 0;
7415
7416 break;
7417
7418 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007419 // if Rn == '1111' then SEE LDRSH (literal);
7420 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007421 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7422 t = Bits32 (opcode, 15, 12);
7423 n = Bits32 (opcode, 19, 16);
7424 m = Bits32 (opcode, 3, 0);
7425
7426 // index = TRUE; add = TRUE; wback = FALSE;
7427 index = true;
7428 add = true;
7429 wback = false;
7430
7431 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7432 shift_t = SRType_LSL;
7433 shift_n = Bits32 (opcode, 5, 4);
7434
7435 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7436 if ((t == 13) || BadReg (m))
7437 return false;
7438
7439 break;
7440
7441 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007442 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007443 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7444 t = Bits32 (opcode, 15, 12);
7445 n = Bits32 (opcode, 19, 16);
7446 m = Bits32 (opcode, 3, 0);
7447
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007448 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007449 index = BitIsSet (opcode, 24);
7450 add = BitIsSet (opcode, 23);
7451 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7452
7453 // (shift_t, shift_n) = (SRType_LSL, 0);
7454 shift_t = SRType_LSL;
7455 shift_n = 0;
7456
7457 // if t == 15 || m == 15 then UNPREDICTABLE;
7458 if ((t == 15) || (m == 15))
7459 return false;
7460
7461 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7462 if (wback && ((n == 15) || (n == t)))
7463 return false;
7464
7465 break;
7466
7467 default:
7468 break;
7469 }
7470
7471 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7472 if (!success)
7473 return false;
7474
7475 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7476 if (!success)
7477 return false;
7478
7479 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7480 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7481
7482 addr_t offset_addr;
7483 addr_t address;
7484
7485 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7486 if (add)
7487 offset_addr = Rn + offset;
7488 else
7489 offset_addr = Rn - offset;
7490
7491 // address = if index then offset_addr else R[n];
7492 if (index)
7493 address = offset_addr;
7494 else
7495 address = Rn;
7496
7497 // data = MemU[address,2];
7498 Register base_reg;
7499 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7500
7501 Register offset_reg;
7502 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7503
7504 EmulateInstruction::Context context;
7505 context.type = eContextRegisterLoad;
7506 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7507
7508 uint64_t data = MemURead (context, address, 2, 0, &success);
7509 if (!success)
7510 return false;
7511
7512 // if wback then R[n] = offset_addr;
7513 if (wback)
7514 {
7515 context.type = eContextAdjustBaseRegister;
7516 context.SetAddress (offset_addr);
7517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7518 return false;
7519 }
7520
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007521 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007522 if (UnalignedSupport() || BitIsClear (address, 0))
7523 {
7524 // R[t] = SignExtend(data, 32);
7525 context.type = eContextRegisterLoad;
7526 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7527
7528 int64_t signed_data = llvm::SignExtend64<16>(data);
7529 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7530 return false;
7531 }
7532 else // Can only apply before ARMv7
7533 {
7534 // R[t] = bits(32) UNKNOWN;
7535 WriteBits32Unknown (t);
7536 }
7537 }
7538 return true;
7539}
Caroline Tice6bf65162011-03-03 17:42:58 +00007540
7541// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7542// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7543bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007544EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007545{
7546#if 0
7547 if ConditionPassed() then
7548 EncodingSpecificOperations();
7549 rotated = ROR(R[m], rotation);
7550 R[d] = SignExtend(rotated<7:0>, 32);
7551#endif
7552
7553 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007554
Greg Clayton7bc39082011-03-24 23:53:38 +00007555 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007556 {
7557 uint32_t d;
7558 uint32_t m;
7559 uint32_t rotation;
7560
7561 // EncodingSpecificOperations();
7562 switch (encoding)
7563 {
7564 case eEncodingT1:
7565 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7566 d = Bits32 (opcode, 2, 0);
7567 m = Bits32 (opcode, 5, 3);
7568 rotation = 0;
7569
7570 break;
7571
7572 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007573 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007574 d = Bits32 (opcode, 11, 8);
7575 m = Bits32 (opcode, 3, 0);
7576 rotation = Bits32 (opcode, 5, 4) << 3;
7577
7578 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7579 if (BadReg (d) || BadReg (m))
7580 return false;
7581
7582 break;
7583
7584 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007585 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007586 d = Bits32 (opcode, 15, 12);
7587 m = Bits32 (opcode, 3, 0);
7588 rotation = Bits32 (opcode, 11, 10) << 3;
7589
7590 // if d == 15 || m == 15 then UNPREDICTABLE;
7591 if ((d == 15) || (m == 15))
7592 return false;
7593
7594 break;
7595
7596 default:
7597 return false;
7598 }
7599
Caroline Tice868198b2011-03-03 18:04:49 +00007600 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7601 if (!success)
7602 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007603
7604 // rotated = ROR(R[m], rotation);
7605 uint64_t rotated = ROR (Rm, rotation);
7606
7607 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007608 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007609
7610 Register source_reg;
7611 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7612
7613 EmulateInstruction::Context context;
7614 context.type = eContextRegisterLoad;
7615 context.SetRegister (source_reg);
7616
Caroline Tice8ce96d92011-03-03 18:27:17 +00007617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007618 return false;
7619 }
7620 return true;
7621}
Caroline Tice291a3e92011-03-02 21:13:44 +00007622
Caroline Tice868198b2011-03-03 18:04:49 +00007623// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7624// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7625bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007626EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007627{
7628#if 0
7629 if ConditionPassed() then
7630 EncodingSpecificOperations();
7631 rotated = ROR(R[m], rotation);
7632 R[d] = SignExtend(rotated<15:0>, 32);
7633#endif
7634
7635 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007636
Greg Clayton7bc39082011-03-24 23:53:38 +00007637 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007638 {
7639 uint32_t d;
7640 uint32_t m;
7641 uint32_t rotation;
7642
7643 // EncodingSpecificOperations();
7644 switch (encoding)
7645 {
7646 case eEncodingT1:
7647 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7648 d = Bits32 (opcode, 2, 0);
7649 m = Bits32 (opcode, 5, 3);
7650 rotation = 0;
7651
7652 break;
7653
7654 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007655 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007656 d = Bits32 (opcode, 11, 8);
7657 m = Bits32 (opcode, 3, 0);
7658 rotation = Bits32 (opcode, 5, 4) << 3;
7659
7660 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7661 if (BadReg (d) || BadReg (m))
7662 return false;
7663
7664 break;
7665
7666 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007667 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007668 d = Bits32 (opcode, 15, 12);
7669 m = Bits32 (opcode, 3, 0);
7670 rotation = Bits32 (opcode, 11, 10) << 3;
7671
7672 // if d == 15 || m == 15 then UNPREDICTABLE;
7673 if ((d == 15) || (m == 15))
7674 return false;
7675
7676 break;
7677
7678 default:
7679 return false;
7680 }
7681
7682 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7683 if (!success)
7684 return false;
7685
7686 // rotated = ROR(R[m], rotation);
7687 uint64_t rotated = ROR (Rm, rotation);
7688
7689 // R[d] = SignExtend(rotated<15:0>, 32);
7690 Register source_reg;
7691 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7692
7693 EmulateInstruction::Context context;
7694 context.type = eContextRegisterLoad;
7695 context.SetRegister (source_reg);
7696
Caroline Tice8ce96d92011-03-03 18:27:17 +00007697 int64_t data = llvm::SignExtend64<16> (rotated);
7698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007699 return false;
7700 }
7701
7702 return true;
7703}
7704
Caroline Tice8ce96d92011-03-03 18:27:17 +00007705// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7706// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7707bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007708EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007709{
7710#if 0
7711 if ConditionPassed() then
7712 EncodingSpecificOperations();
7713 rotated = ROR(R[m], rotation);
7714 R[d] = ZeroExtend(rotated<7:0>, 32);
7715#endif
7716
7717 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007718
Greg Clayton7bc39082011-03-24 23:53:38 +00007719 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007720 {
7721 uint32_t d;
7722 uint32_t m;
7723 uint32_t rotation;
7724
7725 // EncodingSpecificOperations();
7726 switch (encoding)
7727 {
7728 case eEncodingT1:
7729 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7730 d = Bits32 (opcode, 2, 0);
7731 m = Bits32 (opcode, 5, 3);
7732 rotation = 0;
7733
7734 break;
7735
7736 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007737 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007738 d = Bits32 (opcode, 11, 8);
7739 m = Bits32 (opcode, 3, 0);
7740 rotation = Bits32 (opcode, 5, 4) << 3;
7741
7742 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7743 if (BadReg (d) || BadReg (m))
7744 return false;
7745
7746 break;
7747
7748 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007749 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007750 d = Bits32 (opcode, 15, 12);
7751 m = Bits32 (opcode, 3, 0);
7752 rotation = Bits32 (opcode, 11, 10) << 3;
7753
7754 // if d == 15 || m == 15 then UNPREDICTABLE;
7755 if ((d == 15) || (m == 15))
7756 return false;
7757
7758 break;
7759
7760 default:
7761 return false;
7762 }
7763
7764 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7765 if (!success)
7766 return false;
7767
7768 // rotated = ROR(R[m], rotation);
7769 uint64_t rotated = ROR (Rm, rotation);
7770
7771 // R[d] = ZeroExtend(rotated<7:0>, 32);
7772 Register source_reg;
7773 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7774
7775 EmulateInstruction::Context context;
7776 context.type = eContextRegisterLoad;
7777 context.SetRegister (source_reg);
7778
7779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7780 return false;
7781 }
7782 return true;
7783}
7784
Caroline Tice11555f22011-03-03 18:48:58 +00007785// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7786// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7787bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007788EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007789{
7790#if 0
7791 if ConditionPassed() then
7792 EncodingSpecificOperations();
7793 rotated = ROR(R[m], rotation);
7794 R[d] = ZeroExtend(rotated<15:0>, 32);
7795#endif
7796
7797 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007798
Greg Clayton7bc39082011-03-24 23:53:38 +00007799 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007800 {
7801 uint32_t d;
7802 uint32_t m;
7803 uint32_t rotation;
7804
7805 switch (encoding)
7806 {
7807 case eEncodingT1:
7808 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7809 d = Bits32 (opcode, 2, 0);
7810 m = Bits32 (opcode, 5, 3);
7811 rotation = 0;
7812
7813 break;
7814
7815 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007816 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007817 d = Bits32 (opcode, 11, 8);
7818 m = Bits32 (opcode, 3, 0);
7819 rotation = Bits32 (opcode, 5, 4) << 3;
7820
7821 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7822 if (BadReg (d) || BadReg (m))
7823 return false;
7824
7825 break;
7826
7827 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007828 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007829 d = Bits32 (opcode, 15, 12);
7830 m = Bits32 (opcode, 3, 0);
7831 rotation = Bits32 (opcode, 11, 10) << 3;
7832
7833 // if d == 15 || m == 15 then UNPREDICTABLE;
7834 if ((d == 15) || (m == 15))
7835 return false;
7836
7837 break;
7838
7839 default:
7840 return false;
7841 }
7842
7843 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7844 if (!success)
7845 return false;
7846
7847 // rotated = ROR(R[m], rotation);
7848 uint64_t rotated = ROR (Rm, rotation);
7849
7850 // R[d] = ZeroExtend(rotated<15:0>, 32);
7851 Register source_reg;
7852 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7853
7854 EmulateInstruction::Context context;
7855 context.type = eContextRegisterLoad;
7856 context.SetRegister (source_reg);
7857
7858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7859 return false;
7860 }
7861 return true;
7862}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007863
7864// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7865// word respectively.
7866bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007867EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007868{
7869#if 0
7870 if ConditionPassed() then
7871 EncodingSpecificOperations();
7872 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7873 UNPREDICTABLE;
7874 else
7875 address = if increment then R[n] else R[n]-8;
7876 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007877 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007878 BranchWritePC(MemA[address,4]);
7879 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7880#endif
7881
7882 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007883
Greg Clayton7bc39082011-03-24 23:53:38 +00007884 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007885 {
7886 uint32_t n;
7887 bool wback;
7888 bool increment;
7889 bool wordhigher;
7890
7891 // EncodingSpecificOperations();
7892 switch (encoding)
7893 {
7894 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007895 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007896 n = Bits32 (opcode, 19, 16);
7897 wback = BitIsSet (opcode, 21);
7898 increment = false;
7899 wordhigher = false;
7900
7901 // if n == 15 then UNPREDICTABLE;
7902 if (n == 15)
7903 return false;
7904
7905 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7906 if (InITBlock() && !LastInITBlock())
7907 return false;
7908
7909 break;
7910
7911 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007912 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007913 n = Bits32 (opcode, 19, 16);
7914 wback = BitIsSet (opcode, 21);
7915 increment = true;
7916 wordhigher = false;
7917
7918 // if n == 15 then UNPREDICTABLE;
7919 if (n == 15)
7920 return false;
7921
7922 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7923 if (InITBlock() && !LastInITBlock())
7924 return false;
7925
7926 break;
7927
7928 case eEncodingA1:
7929 // n = UInt(Rn);
7930 n = Bits32 (opcode, 19, 16);
7931
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007932 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007933 wback = BitIsSet (opcode, 21);
7934 increment = BitIsSet (opcode, 23);
7935 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7936
7937 // if n == 15 then UNPREDICTABLE;
7938 if (n == 15)
7939 return false;
7940
7941 break;
7942
7943 default:
7944 return false;
7945 }
7946
7947 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7948 if (!CurrentModeIsPrivileged ())
7949 // UNPREDICTABLE;
7950 return false;
7951 else
7952 {
7953 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7954 if (!success)
7955 return false;
7956
7957 addr_t address;
7958 // address = if increment then R[n] else R[n]-8;
7959 if (increment)
7960 address = Rn;
7961 else
7962 address = Rn - 8;
7963
7964 // if wordhigher then address = address+4;
7965 if (wordhigher)
7966 address = address + 4;
7967
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007968 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007969 Register base_reg;
7970 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7971
7972 EmulateInstruction::Context context;
7973 context.type = eContextReturnFromException;
7974 context.SetRegisterPlusOffset (base_reg, address - Rn);
7975
7976 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7977 if (!success)
7978 return false;
7979
7980 CPSRWriteByInstr (data, 15, true);
7981
7982 // BranchWritePC(MemA[address,4]);
7983 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7984 if (!success)
7985 return false;
7986
7987 BranchWritePC (context, data2);
7988
7989 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7990 if (wback)
7991 {
7992 context.type = eContextAdjustBaseRegister;
7993 if (increment)
7994 {
7995 context.SetOffset (8);
7996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7997 return false;
7998 }
7999 else
8000 {
8001 context.SetOffset (-8);
8002 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8003 return false;
8004 }
8005 } // if wback
8006 }
8007 } // if ConditionPassed()
8008 return true;
8009}
Caroline Tice11555f22011-03-03 18:48:58 +00008010
Johnny Chen2115b412011-02-21 23:42:44 +00008011// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8012// and writes the result to the destination register. It can optionally update the condition flags based on
8013// the result.
8014bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008015EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008016{
8017#if 0
8018 // ARM pseudo code...
8019 if ConditionPassed() then
8020 EncodingSpecificOperations();
8021 result = R[n] EOR imm32;
8022 if d == 15 then // Can only occur for ARM encoding
8023 ALUWritePC(result); // setflags is always FALSE here
8024 else
8025 R[d] = result;
8026 if setflags then
8027 APSR.N = result<31>;
8028 APSR.Z = IsZeroBit(result);
8029 APSR.C = carry;
8030 // APSR.V unchanged
8031#endif
8032
8033 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008034
Greg Clayton7bc39082011-03-24 23:53:38 +00008035 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008036 {
8037 uint32_t Rd, Rn;
8038 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8039 bool setflags;
8040 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8041 switch (encoding)
8042 {
8043 case eEncodingT1:
8044 Rd = Bits32(opcode, 11, 8);
8045 Rn = Bits32(opcode, 19, 16);
8046 setflags = BitIsSet(opcode, 20);
8047 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8048 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8049 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008050 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008051 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8052 return false;
8053 break;
8054 case eEncodingA1:
8055 Rd = Bits32(opcode, 15, 12);
8056 Rn = Bits32(opcode, 19, 16);
8057 setflags = BitIsSet(opcode, 20);
8058 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8059 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8060 // TODO: Emulate SUBS PC, LR and related instructions.
8061 if (Rd == 15 && setflags)
8062 return false;
8063 break;
8064 default:
8065 return false;
8066 }
8067
8068 // Read the first operand.
8069 uint32_t val1 = ReadCoreReg(Rn, &success);
8070 if (!success)
8071 return false;
8072
8073 uint32_t result = val1 ^ imm32;
8074
8075 EmulateInstruction::Context context;
8076 context.type = EmulateInstruction::eContextImmediate;
8077 context.SetNoArgs ();
8078
8079 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8080 return false;
8081 }
8082 return true;
8083}
8084
8085// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8086// optionally-shifted register value, and writes the result to the destination register.
8087// It can optionally update the condition flags based on the result.
8088bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008089EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008090{
8091#if 0
8092 // ARM pseudo code...
8093 if ConditionPassed() then
8094 EncodingSpecificOperations();
8095 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8096 result = R[n] EOR shifted;
8097 if d == 15 then // Can only occur for ARM encoding
8098 ALUWritePC(result); // setflags is always FALSE here
8099 else
8100 R[d] = result;
8101 if setflags then
8102 APSR.N = result<31>;
8103 APSR.Z = IsZeroBit(result);
8104 APSR.C = carry;
8105 // APSR.V unchanged
8106#endif
8107
8108 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008109
Greg Clayton7bc39082011-03-24 23:53:38 +00008110 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008111 {
8112 uint32_t Rd, Rn, Rm;
8113 ARM_ShifterType shift_t;
8114 uint32_t shift_n; // the shift applied to the value read from Rm
8115 bool setflags;
8116 uint32_t carry;
8117 switch (encoding)
8118 {
8119 case eEncodingT1:
8120 Rd = Rn = Bits32(opcode, 2, 0);
8121 Rm = Bits32(opcode, 5, 3);
8122 setflags = !InITBlock();
8123 shift_t = SRType_LSL;
8124 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008125 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008126 case eEncodingT2:
8127 Rd = Bits32(opcode, 11, 8);
8128 Rn = Bits32(opcode, 19, 16);
8129 Rm = Bits32(opcode, 3, 0);
8130 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008131 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8132 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008133 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008134 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008135 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8136 return false;
8137 break;
8138 case eEncodingA1:
8139 Rd = Bits32(opcode, 15, 12);
8140 Rn = Bits32(opcode, 19, 16);
8141 Rm = Bits32(opcode, 3, 0);
8142 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008143 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008144 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8145 // TODO: Emulate SUBS PC, LR and related instructions.
8146 if (Rd == 15 && setflags)
8147 return false;
8148 break;
8149 default:
8150 return false;
8151 }
8152
8153 // Read the first operand.
8154 uint32_t val1 = ReadCoreReg(Rn, &success);
8155 if (!success)
8156 return false;
8157
8158 // Read the second operand.
8159 uint32_t val2 = ReadCoreReg(Rm, &success);
8160 if (!success)
8161 return false;
8162
8163 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8164 uint32_t result = val1 ^ shifted;
8165
8166 EmulateInstruction::Context context;
8167 context.type = EmulateInstruction::eContextImmediate;
8168 context.SetNoArgs ();
8169
8170 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8171 return false;
8172 }
8173 return true;
8174}
8175
Johnny Chen7c5234d2011-02-18 23:41:11 +00008176// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8177// writes the result to the destination register. It can optionally update the condition flags based
8178// on the result.
8179bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008180EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008181{
8182#if 0
8183 // ARM pseudo code...
8184 if ConditionPassed() then
8185 EncodingSpecificOperations();
8186 result = R[n] OR imm32;
8187 if d == 15 then // Can only occur for ARM encoding
8188 ALUWritePC(result); // setflags is always FALSE here
8189 else
8190 R[d] = result;
8191 if setflags then
8192 APSR.N = result<31>;
8193 APSR.Z = IsZeroBit(result);
8194 APSR.C = carry;
8195 // APSR.V unchanged
8196#endif
8197
8198 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008199
Greg Clayton7bc39082011-03-24 23:53:38 +00008200 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008201 {
8202 uint32_t Rd, Rn;
8203 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8204 bool setflags;
8205 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8206 switch (encoding)
8207 {
8208 case eEncodingT1:
8209 Rd = Bits32(opcode, 11, 8);
8210 Rn = Bits32(opcode, 19, 16);
8211 setflags = BitIsSet(opcode, 20);
8212 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008213 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008214 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008215 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008216 if (BadReg(Rd) || Rn == 13)
8217 return false;
8218 break;
8219 case eEncodingA1:
8220 Rd = Bits32(opcode, 15, 12);
8221 Rn = Bits32(opcode, 19, 16);
8222 setflags = BitIsSet(opcode, 20);
8223 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8224 // TODO: Emulate SUBS PC, LR and related instructions.
8225 if (Rd == 15 && setflags)
8226 return false;
8227 break;
8228 default:
8229 return false;
8230 }
8231
8232 // Read the first operand.
8233 uint32_t val1 = ReadCoreReg(Rn, &success);
8234 if (!success)
8235 return false;
8236
8237 uint32_t result = val1 | imm32;
8238
8239 EmulateInstruction::Context context;
8240 context.type = EmulateInstruction::eContextImmediate;
8241 context.SetNoArgs ();
8242
8243 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8244 return false;
8245 }
8246 return true;
8247}
8248
8249// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8250// value, and writes the result to the destination register. It can optionally update the condition flags based
8251// on the result.
8252bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008253EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008254{
8255#if 0
8256 // ARM pseudo code...
8257 if ConditionPassed() then
8258 EncodingSpecificOperations();
8259 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8260 result = R[n] OR shifted;
8261 if d == 15 then // Can only occur for ARM encoding
8262 ALUWritePC(result); // setflags is always FALSE here
8263 else
8264 R[d] = result;
8265 if setflags then
8266 APSR.N = result<31>;
8267 APSR.Z = IsZeroBit(result);
8268 APSR.C = carry;
8269 // APSR.V unchanged
8270#endif
8271
8272 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008273
Greg Clayton7bc39082011-03-24 23:53:38 +00008274 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008275 {
8276 uint32_t Rd, Rn, Rm;
8277 ARM_ShifterType shift_t;
8278 uint32_t shift_n; // the shift applied to the value read from Rm
8279 bool setflags;
8280 uint32_t carry;
8281 switch (encoding)
8282 {
8283 case eEncodingT1:
8284 Rd = Rn = Bits32(opcode, 2, 0);
8285 Rm = Bits32(opcode, 5, 3);
8286 setflags = !InITBlock();
8287 shift_t = SRType_LSL;
8288 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008289 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008290 case eEncodingT2:
8291 Rd = Bits32(opcode, 11, 8);
8292 Rn = Bits32(opcode, 19, 16);
8293 Rm = Bits32(opcode, 3, 0);
8294 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008295 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8296 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008297 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008298 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008299 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8300 return false;
8301 break;
8302 case eEncodingA1:
8303 Rd = Bits32(opcode, 15, 12);
8304 Rn = Bits32(opcode, 19, 16);
8305 Rm = Bits32(opcode, 3, 0);
8306 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008307 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008308 // TODO: Emulate SUBS PC, LR and related instructions.
8309 if (Rd == 15 && setflags)
8310 return false;
8311 break;
8312 default:
8313 return false;
8314 }
8315
8316 // Read the first operand.
8317 uint32_t val1 = ReadCoreReg(Rn, &success);
8318 if (!success)
8319 return false;
8320
8321 // Read the second operand.
8322 uint32_t val2 = ReadCoreReg(Rm, &success);
8323 if (!success)
8324 return false;
8325
8326 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008327 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008328
8329 EmulateInstruction::Context context;
8330 context.type = EmulateInstruction::eContextImmediate;
8331 context.SetNoArgs ();
8332
8333 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8334 return false;
8335 }
8336 return true;
8337}
8338
Johnny Chened32e7c2011-02-22 23:42:58 +00008339// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8340// the destination register. It can optionally update the condition flags based on the result.
8341bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008342EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008343{
8344#if 0
8345 // ARM pseudo code...
8346 if ConditionPassed() then
8347 EncodingSpecificOperations();
8348 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8349 if d == 15 then // Can only occur for ARM encoding
8350 ALUWritePC(result); // setflags is always FALSE here
8351 else
8352 R[d] = result;
8353 if setflags then
8354 APSR.N = result<31>;
8355 APSR.Z = IsZeroBit(result);
8356 APSR.C = carry;
8357 APSR.V = overflow;
8358#endif
8359
8360 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008361
8362 uint32_t Rd; // the destination register
8363 uint32_t Rn; // the first operand
8364 bool setflags;
8365 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8366 switch (encoding) {
8367 case eEncodingT1:
8368 Rd = Bits32(opcode, 2, 0);
8369 Rn = Bits32(opcode, 5, 3);
8370 setflags = !InITBlock();
8371 imm32 = 0;
8372 break;
8373 case eEncodingT2:
8374 Rd = Bits32(opcode, 11, 8);
8375 Rn = Bits32(opcode, 19, 16);
8376 setflags = BitIsSet(opcode, 20);
8377 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8378 if (BadReg(Rd) || BadReg(Rn))
8379 return false;
8380 break;
8381 case eEncodingA1:
8382 Rd = Bits32(opcode, 15, 12);
8383 Rn = Bits32(opcode, 19, 16);
8384 setflags = BitIsSet(opcode, 20);
8385 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8386 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8387 // TODO: Emulate SUBS PC, LR and related instructions.
8388 if (Rd == 15 && setflags)
8389 return false;
8390 break;
8391 default:
8392 return false;
8393 }
8394 // Read the register value from the operand register Rn.
8395 uint32_t reg_val = ReadCoreReg(Rn, &success);
8396 if (!success)
8397 return false;
8398
8399 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8400
8401 EmulateInstruction::Context context;
8402 context.type = EmulateInstruction::eContextImmediate;
8403 context.SetNoArgs ();
8404
8405 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8406 return false;
8407
8408 return true;
8409}
8410
8411// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8412// result to the destination register. It can optionally update the condition flags based on the result.
8413bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008414EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008415{
8416#if 0
8417 // ARM pseudo code...
8418 if ConditionPassed() then
8419 EncodingSpecificOperations();
8420 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8421 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8422 if d == 15 then // Can only occur for ARM encoding
8423 ALUWritePC(result); // setflags is always FALSE here
8424 else
8425 R[d] = result;
8426 if setflags then
8427 APSR.N = result<31>;
8428 APSR.Z = IsZeroBit(result);
8429 APSR.C = carry;
8430 APSR.V = overflow;
8431#endif
8432
8433 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008434
8435 uint32_t Rd; // the destination register
8436 uint32_t Rn; // the first operand
8437 uint32_t Rm; // the second operand
8438 bool setflags;
8439 ARM_ShifterType shift_t;
8440 uint32_t shift_n; // the shift applied to the value read from Rm
8441 switch (encoding) {
8442 case eEncodingT1:
8443 Rd = Bits32(opcode, 11, 8);
8444 Rn = Bits32(opcode, 19, 16);
8445 Rm = Bits32(opcode, 3, 0);
8446 setflags = BitIsSet(opcode, 20);
8447 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8448 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8449 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8450 return false;
8451 break;
8452 case eEncodingA1:
8453 Rd = Bits32(opcode, 15, 12);
8454 Rn = Bits32(opcode, 19, 16);
8455 Rm = Bits32(opcode, 3, 0);
8456 setflags = BitIsSet(opcode, 20);
8457 shift_n = DecodeImmShiftARM(opcode, shift_t);
8458 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8459 // TODO: Emulate SUBS PC, LR and related instructions.
8460 if (Rd == 15 && setflags)
8461 return false;
8462 break;
8463 default:
8464 return false;
8465 }
8466 // Read the register value from register Rn.
8467 uint32_t val1 = ReadCoreReg(Rn, &success);
8468 if (!success)
8469 return false;
8470
8471 // Read the register value from register Rm.
8472 uint32_t val2 = ReadCoreReg(Rm, &success);
8473 if (!success)
8474 return false;
8475
8476 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8477 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8478
8479 EmulateInstruction::Context context;
8480 context.type = EmulateInstruction::eContextImmediate;
8481 context.SetNoArgs();
8482 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8483 return false;
8484
8485 return true;
8486}
8487
Johnny Chen90e607b2011-02-23 00:07:09 +00008488// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8489// an immediate value, and writes the result to the destination register. It can optionally update the condition
8490// flags based on the result.
8491bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008492EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008493{
8494#if 0
8495 // ARM pseudo code...
8496 if ConditionPassed() then
8497 EncodingSpecificOperations();
8498 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8499 if d == 15 then
8500 ALUWritePC(result); // setflags is always FALSE here
8501 else
8502 R[d] = result;
8503 if setflags then
8504 APSR.N = result<31>;
8505 APSR.Z = IsZeroBit(result);
8506 APSR.C = carry;
8507 APSR.V = overflow;
8508#endif
8509
8510 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008511
8512 uint32_t Rd; // the destination register
8513 uint32_t Rn; // the first operand
8514 bool setflags;
8515 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8516 switch (encoding) {
8517 case eEncodingA1:
8518 Rd = Bits32(opcode, 15, 12);
8519 Rn = Bits32(opcode, 19, 16);
8520 setflags = BitIsSet(opcode, 20);
8521 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8522 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8523 // TODO: Emulate SUBS PC, LR and related instructions.
8524 if (Rd == 15 && setflags)
8525 return false;
8526 break;
8527 default:
8528 return false;
8529 }
8530 // Read the register value from the operand register Rn.
8531 uint32_t reg_val = ReadCoreReg(Rn, &success);
8532 if (!success)
8533 return false;
8534
8535 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8536
8537 EmulateInstruction::Context context;
8538 context.type = EmulateInstruction::eContextImmediate;
8539 context.SetNoArgs ();
8540
8541 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8542 return false;
8543
8544 return true;
8545}
8546
8547// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8548// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8549// condition flags based on the result.
8550bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008551EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008552{
8553#if 0
8554 // ARM pseudo code...
8555 if ConditionPassed() then
8556 EncodingSpecificOperations();
8557 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8558 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8559 if d == 15 then
8560 ALUWritePC(result); // setflags is always FALSE here
8561 else
8562 R[d] = result;
8563 if setflags then
8564 APSR.N = result<31>;
8565 APSR.Z = IsZeroBit(result);
8566 APSR.C = carry;
8567 APSR.V = overflow;
8568#endif
8569
8570 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008571
8572 uint32_t Rd; // the destination register
8573 uint32_t Rn; // the first operand
8574 uint32_t Rm; // the second operand
8575 bool setflags;
8576 ARM_ShifterType shift_t;
8577 uint32_t shift_n; // the shift applied to the value read from Rm
8578 switch (encoding) {
8579 case eEncodingA1:
8580 Rd = Bits32(opcode, 15, 12);
8581 Rn = Bits32(opcode, 19, 16);
8582 Rm = Bits32(opcode, 3, 0);
8583 setflags = BitIsSet(opcode, 20);
8584 shift_n = DecodeImmShiftARM(opcode, shift_t);
8585 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8586 // TODO: Emulate SUBS PC, LR and related instructions.
8587 if (Rd == 15 && setflags)
8588 return false;
8589 break;
8590 default:
8591 return false;
8592 }
8593 // Read the register value from register Rn.
8594 uint32_t val1 = ReadCoreReg(Rn, &success);
8595 if (!success)
8596 return false;
8597
8598 // Read the register value from register Rm.
8599 uint32_t val2 = ReadCoreReg(Rm, &success);
8600 if (!success)
8601 return false;
8602
8603 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8604 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8605
8606 EmulateInstruction::Context context;
8607 context.type = EmulateInstruction::eContextImmediate;
8608 context.SetNoArgs();
8609 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8610 return false;
8611
8612 return true;
8613}
8614
Johnny Chen9b381772011-02-23 01:01:21 +00008615// Subtract with Carry (immediate) subtracts an immediate value and the value of
8616// NOT (Carry flag) from a register value, and writes the result to the destination register.
8617// It can optionally update the condition flags based on the result.
8618bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008619EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008620{
8621#if 0
8622 // ARM pseudo code...
8623 if ConditionPassed() then
8624 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008625 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008626 if d == 15 then // Can only occur for ARM encoding
8627 ALUWritePC(result); // setflags is always FALSE here
8628 else
8629 R[d] = result;
8630 if setflags then
8631 APSR.N = result<31>;
8632 APSR.Z = IsZeroBit(result);
8633 APSR.C = carry;
8634 APSR.V = overflow;
8635#endif
8636
8637 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008638
8639 uint32_t Rd; // the destination register
8640 uint32_t Rn; // the first operand
8641 bool setflags;
8642 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8643 switch (encoding) {
8644 case eEncodingT1:
8645 Rd = Bits32(opcode, 11, 8);
8646 Rn = Bits32(opcode, 19, 16);
8647 setflags = BitIsSet(opcode, 20);
8648 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8649 if (BadReg(Rd) || BadReg(Rn))
8650 return false;
8651 break;
8652 case eEncodingA1:
8653 Rd = Bits32(opcode, 15, 12);
8654 Rn = Bits32(opcode, 19, 16);
8655 setflags = BitIsSet(opcode, 20);
8656 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8657 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8658 // TODO: Emulate SUBS PC, LR and related instructions.
8659 if (Rd == 15 && setflags)
8660 return false;
8661 break;
8662 default:
8663 return false;
8664 }
8665 // Read the register value from the operand register Rn.
8666 uint32_t reg_val = ReadCoreReg(Rn, &success);
8667 if (!success)
8668 return false;
8669
8670 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8671
8672 EmulateInstruction::Context context;
8673 context.type = EmulateInstruction::eContextImmediate;
8674 context.SetNoArgs ();
8675
8676 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8677 return false;
8678
8679 return true;
8680}
8681
8682// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8683// NOT (Carry flag) from a register value, and writes the result to the destination register.
8684// It can optionally update the condition flags based on the result.
8685bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008686EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008687{
8688#if 0
8689 // ARM pseudo code...
8690 if ConditionPassed() then
8691 EncodingSpecificOperations();
8692 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8693 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8694 if d == 15 then // Can only occur for ARM encoding
8695 ALUWritePC(result); // setflags is always FALSE here
8696 else
8697 R[d] = result;
8698 if setflags then
8699 APSR.N = result<31>;
8700 APSR.Z = IsZeroBit(result);
8701 APSR.C = carry;
8702 APSR.V = overflow;
8703#endif
8704
8705 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008706
8707 uint32_t Rd; // the destination register
8708 uint32_t Rn; // the first operand
8709 uint32_t Rm; // the second operand
8710 bool setflags;
8711 ARM_ShifterType shift_t;
8712 uint32_t shift_n; // the shift applied to the value read from Rm
8713 switch (encoding) {
8714 case eEncodingT1:
8715 Rd = Rn = Bits32(opcode, 2, 0);
8716 Rm = Bits32(opcode, 5, 3);
8717 setflags = !InITBlock();
8718 shift_t = SRType_LSL;
8719 shift_n = 0;
8720 break;
8721 case eEncodingT2:
8722 Rd = Bits32(opcode, 11, 8);
8723 Rn = Bits32(opcode, 19, 16);
8724 Rm = Bits32(opcode, 3, 0);
8725 setflags = BitIsSet(opcode, 20);
8726 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8727 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8728 return false;
8729 break;
8730 case eEncodingA1:
8731 Rd = Bits32(opcode, 15, 12);
8732 Rn = Bits32(opcode, 19, 16);
8733 Rm = Bits32(opcode, 3, 0);
8734 setflags = BitIsSet(opcode, 20);
8735 shift_n = DecodeImmShiftARM(opcode, shift_t);
8736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8737 // TODO: Emulate SUBS PC, LR and related instructions.
8738 if (Rd == 15 && setflags)
8739 return false;
8740 break;
8741 default:
8742 return false;
8743 }
8744 // Read the register value from register Rn.
8745 uint32_t val1 = ReadCoreReg(Rn, &success);
8746 if (!success)
8747 return false;
8748
8749 // Read the register value from register Rm.
8750 uint32_t val2 = ReadCoreReg(Rm, &success);
8751 if (!success)
8752 return false;
8753
8754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8755 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8756
8757 EmulateInstruction::Context context;
8758 context.type = EmulateInstruction::eContextImmediate;
8759 context.SetNoArgs();
8760 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8761 return false;
8762
8763 return true;
8764}
8765
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008766// This instruction subtracts an immediate value from a register value, and writes the result
8767// to the destination register. It can optionally update the condition flags based on the result.
8768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008769EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008770{
8771#if 0
8772 // ARM pseudo code...
8773 if ConditionPassed() then
8774 EncodingSpecificOperations();
8775 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8776 R[d] = result;
8777 if setflags then
8778 APSR.N = result<31>;
8779 APSR.Z = IsZeroBit(result);
8780 APSR.C = carry;
8781 APSR.V = overflow;
8782#endif
8783
8784 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008785
8786 uint32_t Rd; // the destination register
8787 uint32_t Rn; // the first operand
8788 bool setflags;
8789 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8790 switch (encoding) {
8791 case eEncodingT1:
8792 Rd = Bits32(opcode, 2, 0);
8793 Rn = Bits32(opcode, 5, 3);
8794 setflags = !InITBlock();
8795 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8796 break;
8797 case eEncodingT2:
8798 Rd = Rn = Bits32(opcode, 10, 8);
8799 setflags = !InITBlock();
8800 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8801 break;
8802 case eEncodingT3:
8803 Rd = Bits32(opcode, 11, 8);
8804 Rn = Bits32(opcode, 19, 16);
8805 setflags = BitIsSet(opcode, 20);
8806 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8807
8808 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8809 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008810 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008811
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008812 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008813 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008814 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008815
8816 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8817 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8818 return false;
8819 break;
8820 case eEncodingT4:
8821 Rd = Bits32(opcode, 11, 8);
8822 Rn = Bits32(opcode, 19, 16);
8823 setflags = BitIsSet(opcode, 20);
8824 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8825
8826 // if Rn == '1111' then SEE ADR;
8827 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008828 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008829
8830 // if Rn == '1101' then SEE SUB (SP minus immediate);
8831 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008832 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008833
8834 if (BadReg(Rd))
8835 return false;
8836 break;
8837 default:
8838 return false;
8839 }
8840 // Read the register value from the operand register Rn.
8841 uint32_t reg_val = ReadCoreReg(Rn, &success);
8842 if (!success)
8843 return false;
8844
8845 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8846
8847 EmulateInstruction::Context context;
8848 context.type = EmulateInstruction::eContextImmediate;
8849 context.SetNoArgs ();
8850
8851 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8852 return false;
8853
8854 return true;
8855}
8856
8857// This instruction subtracts an immediate value from a register value, and writes the result
8858// to the destination register. It can optionally update the condition flags based on the result.
8859bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008860EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008861{
8862#if 0
8863 // ARM pseudo code...
8864 if ConditionPassed() then
8865 EncodingSpecificOperations();
8866 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8867 if d == 15 then
8868 ALUWritePC(result); // setflags is always FALSE here
8869 else
8870 R[d] = result;
8871 if setflags then
8872 APSR.N = result<31>;
8873 APSR.Z = IsZeroBit(result);
8874 APSR.C = carry;
8875 APSR.V = overflow;
8876#endif
8877
8878 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008879
8880 uint32_t Rd; // the destination register
8881 uint32_t Rn; // the first operand
8882 bool setflags;
8883 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8884 switch (encoding) {
8885 case eEncodingA1:
8886 Rd = Bits32(opcode, 15, 12);
8887 Rn = Bits32(opcode, 19, 16);
8888 setflags = BitIsSet(opcode, 20);
8889 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8890
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008891 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008892 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008893 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008894
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008895 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008896 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008897 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008898
8899 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8900 // TODO: Emulate SUBS PC, LR and related instructions.
8901 if (Rd == 15 && setflags)
8902 return false;
8903 break;
8904 default:
8905 return false;
8906 }
8907 // Read the register value from the operand register Rn.
8908 uint32_t reg_val = ReadCoreReg(Rn, &success);
8909 if (!success)
8910 return false;
8911
8912 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8913
8914 EmulateInstruction::Context context;
8915 context.type = EmulateInstruction::eContextImmediate;
8916 context.SetNoArgs ();
8917
8918 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8919 return false;
8920
8921 return true;
8922}
8923
Johnny Chen2115b412011-02-21 23:42:44 +00008924// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8925// immediate value. It updates the condition flags based on the result, and discards the result.
8926bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008927EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008928{
8929#if 0
8930 // ARM pseudo code...
8931 if ConditionPassed() then
8932 EncodingSpecificOperations();
8933 result = R[n] EOR imm32;
8934 APSR.N = result<31>;
8935 APSR.Z = IsZeroBit(result);
8936 APSR.C = carry;
8937 // APSR.V unchanged
8938#endif
8939
8940 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008941
Greg Clayton7bc39082011-03-24 23:53:38 +00008942 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008943 {
8944 uint32_t Rn;
8945 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8946 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8947 switch (encoding)
8948 {
8949 case eEncodingT1:
8950 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008951 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008952 if (BadReg(Rn))
8953 return false;
8954 break;
8955 case eEncodingA1:
8956 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008957 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008958 break;
8959 default:
8960 return false;
8961 }
8962
8963 // Read the first operand.
8964 uint32_t val1 = ReadCoreReg(Rn, &success);
8965 if (!success)
8966 return false;
8967
8968 uint32_t result = val1 ^ imm32;
8969
8970 EmulateInstruction::Context context;
8971 context.type = EmulateInstruction::eContextImmediate;
8972 context.SetNoArgs ();
8973
8974 if (!WriteFlags(context, result, carry))
8975 return false;
8976 }
8977 return true;
8978}
8979
8980// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8981// optionally-shifted register value. It updates the condition flags based on the result, and discards
8982// the result.
8983bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008984EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008985{
8986#if 0
8987 // ARM pseudo code...
8988 if ConditionPassed() then
8989 EncodingSpecificOperations();
8990 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8991 result = R[n] EOR shifted;
8992 APSR.N = result<31>;
8993 APSR.Z = IsZeroBit(result);
8994 APSR.C = carry;
8995 // APSR.V unchanged
8996#endif
8997
8998 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008999
Greg Clayton7bc39082011-03-24 23:53:38 +00009000 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009001 {
9002 uint32_t Rn, Rm;
9003 ARM_ShifterType shift_t;
9004 uint32_t shift_n; // the shift applied to the value read from Rm
9005 uint32_t carry;
9006 switch (encoding)
9007 {
9008 case eEncodingT1:
9009 Rn = Bits32(opcode, 19, 16);
9010 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009011 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009012 if (BadReg(Rn) || BadReg(Rm))
9013 return false;
9014 break;
9015 case eEncodingA1:
9016 Rn = Bits32(opcode, 19, 16);
9017 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009018 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009019 break;
9020 default:
9021 return false;
9022 }
9023
9024 // Read the first operand.
9025 uint32_t val1 = ReadCoreReg(Rn, &success);
9026 if (!success)
9027 return false;
9028
9029 // Read the second operand.
9030 uint32_t val2 = ReadCoreReg(Rm, &success);
9031 if (!success)
9032 return false;
9033
9034 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9035 uint32_t result = val1 ^ shifted;
9036
9037 EmulateInstruction::Context context;
9038 context.type = EmulateInstruction::eContextImmediate;
9039 context.SetNoArgs ();
9040
9041 if (!WriteFlags(context, result, carry))
9042 return false;
9043 }
9044 return true;
9045}
9046
Johnny Chende3cce32011-02-21 21:24:49 +00009047// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9048// It updates the condition flags based on the result, and discards the result.
9049bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009050EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009051{
9052#if 0
9053 // ARM pseudo code...
9054 if ConditionPassed() then
9055 EncodingSpecificOperations();
9056 result = R[n] AND imm32;
9057 APSR.N = result<31>;
9058 APSR.Z = IsZeroBit(result);
9059 APSR.C = carry;
9060 // APSR.V unchanged
9061#endif
9062
9063 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009064
Greg Clayton7bc39082011-03-24 23:53:38 +00009065 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009066 {
9067 uint32_t Rn;
9068 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9069 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9070 switch (encoding)
9071 {
9072 case eEncodingT1:
9073 Rn = Bits32(opcode, 19, 16);
9074 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9075 if (BadReg(Rn))
9076 return false;
9077 break;
9078 case eEncodingA1:
9079 Rn = Bits32(opcode, 19, 16);
9080 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9081 break;
9082 default:
9083 return false;
9084 }
9085
9086 // Read the first operand.
9087 uint32_t val1 = ReadCoreReg(Rn, &success);
9088 if (!success)
9089 return false;
9090
9091 uint32_t result = val1 & imm32;
9092
9093 EmulateInstruction::Context context;
9094 context.type = EmulateInstruction::eContextImmediate;
9095 context.SetNoArgs ();
9096
9097 if (!WriteFlags(context, result, carry))
9098 return false;
9099 }
9100 return true;
9101}
9102
9103// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9104// It updates the condition flags based on the result, and discards the result.
9105bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009106EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009107{
9108#if 0
9109 // ARM pseudo code...
9110 if ConditionPassed() then
9111 EncodingSpecificOperations();
9112 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9113 result = R[n] AND shifted;
9114 APSR.N = result<31>;
9115 APSR.Z = IsZeroBit(result);
9116 APSR.C = carry;
9117 // APSR.V unchanged
9118#endif
9119
9120 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009121
Greg Clayton7bc39082011-03-24 23:53:38 +00009122 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009123 {
9124 uint32_t Rn, Rm;
9125 ARM_ShifterType shift_t;
9126 uint32_t shift_n; // the shift applied to the value read from Rm
9127 uint32_t carry;
9128 switch (encoding)
9129 {
9130 case eEncodingT1:
9131 Rn = Bits32(opcode, 2, 0);
9132 Rm = Bits32(opcode, 5, 3);
9133 shift_t = SRType_LSL;
9134 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009135 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009136 case eEncodingT2:
9137 Rn = Bits32(opcode, 19, 16);
9138 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009139 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009140 if (BadReg(Rn) || BadReg(Rm))
9141 return false;
9142 break;
9143 case eEncodingA1:
9144 Rn = Bits32(opcode, 19, 16);
9145 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009146 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009147 break;
9148 default:
9149 return false;
9150 }
9151
9152 // Read the first operand.
9153 uint32_t val1 = ReadCoreReg(Rn, &success);
9154 if (!success)
9155 return false;
9156
9157 // Read the second operand.
9158 uint32_t val2 = ReadCoreReg(Rm, &success);
9159 if (!success)
9160 return false;
9161
9162 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9163 uint32_t result = val1 & shifted;
9164
9165 EmulateInstruction::Context context;
9166 context.type = EmulateInstruction::eContextImmediate;
9167 context.SetNoArgs ();
9168
9169 if (!WriteFlags(context, result, carry))
9170 return false;
9171 }
9172 return true;
9173}
9174
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009175EmulateInstructionARM::ARMOpcode*
9176EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009177{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009178 static ARMOpcode
9179 g_arm_opcodes[] =
9180 {
9181 //----------------------------------------------------------------------
9182 // Prologue instructions
9183 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009184
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009185 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009186 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9187 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009188
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009189 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009190 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009191 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009192 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009193 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9194 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009195 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009196
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009197 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009198 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009199
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009200 // push one register
9201 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009202 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009203
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009204 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009205 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9206 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009207
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009208 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009209 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009210 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009211
Johnny Chen9f687722011-02-18 00:02:28 +00009212 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9213 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009214 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009215 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9216
9217 //----------------------------------------------------------------------
9218 // Supervisor Call (previously Software Interrupt)
9219 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009220 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9221
9222 //----------------------------------------------------------------------
9223 // Branch instructions
9224 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009225 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009226 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9227 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9228 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9229 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009230 // for example, "bx lr"
9231 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009232 // bxj
9233 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009234
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009235 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009236 // Data-processing instructions
9237 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009238 // adc (immediate)
9239 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9240 // adc (register)
9241 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009242 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009243 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009244 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009245 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009246 // adr
9247 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9248 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009249 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009250 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009251 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009252 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009253 // bic (immediate)
9254 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9255 // bic (register)
9256 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009257 // eor (immediate)
9258 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9259 // eor (register)
9260 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009261 // orr (immediate)
9262 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9263 // orr (register)
9264 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009265 // rsb (immediate)
9266 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9267 // rsb (register)
9268 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009269 // rsc (immediate)
9270 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9271 // rsc (register)
9272 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009273 // sbc (immediate)
9274 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9275 // sbc (register)
9276 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009277 // sub (immediate, ARM)
9278 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009279 // sub (sp minus immediate)
9280 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009281 // teq (immediate)
9282 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9283 // teq (register)
9284 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009285 // tst (immediate)
9286 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9287 // tst (register)
9288 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9289
Caroline Tice89c6d582011-03-29 19:53:44 +00009290 // mov (immediate)
9291 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
9292 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +00009293 // mov (register)
9294 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009295 // mvn (immediate)
9296 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9297 // mvn (register)
9298 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009299 // cmn (immediate)
9300 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9301 // cmn (register)
9302 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009303 // cmp (immediate)
9304 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9305 // cmp (register)
9306 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009307 // asr (immediate)
9308 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009309 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009310 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009311 // lsl (immediate)
9312 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9313 // lsl (register)
9314 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9315 // lsr (immediate)
9316 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9317 // lsr (register)
9318 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009319 // rrx is a special case encoding of ror (immediate)
9320 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9321 // ror (immediate)
9322 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9323 // ror (register)
9324 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009325 // mul
9326 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009327
9328 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009329 // Load instructions
9330 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009331 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009332 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009333 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009334 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009335 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009336 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009337 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009338 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009339 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009340 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009341 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009342 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009343 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009344 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009345 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9346 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009347
9348 //----------------------------------------------------------------------
9349 // Store instructions
9350 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009351 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009352 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009353 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009354 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009355 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009356 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009357
Caroline Tice6bf65162011-03-03 17:42:58 +00009358 //----------------------------------------------------------------------
9359 // Other instructions
9360 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009361 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009362 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009363 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009364 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9365 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009366
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009367 };
9368 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9369
9370 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9371 {
9372 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9373 return &g_arm_opcodes[i];
9374 }
9375 return NULL;
9376}
Greg Clayton64c84432011-01-21 22:02:52 +00009377
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009378
9379EmulateInstructionARM::ARMOpcode*
9380EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009381{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009382
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009383 static ARMOpcode
9384 g_thumb_opcodes[] =
9385 {
9386 //----------------------------------------------------------------------
9387 // Prologue instructions
9388 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009389
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009390 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009391 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9392 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9393 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009394
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009395 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009396 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009397 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009398 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009399 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009400 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009401
Johnny Chen864a8e82011-02-18 00:07:39 +00009402 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009403 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009404
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009405 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009406 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009407 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009408 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9409 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009410
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009411 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009412 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9413 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009414
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009415 //----------------------------------------------------------------------
9416 // Epilogue instructions
9417 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009418
Caroline Ticee2212882011-03-22 22:38:28 +00009419 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009420 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009421 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9422 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9423 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009424 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9425 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009426
9427 //----------------------------------------------------------------------
9428 // Supervisor Call (previously Software Interrupt)
9429 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009430 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9431
9432 //----------------------------------------------------------------------
9433 // If Then makes up to four following instructions conditional.
9434 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009435 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9436
9437 //----------------------------------------------------------------------
9438 // Branch instructions
9439 //----------------------------------------------------------------------
9440 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9441 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +00009442 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009443 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009444 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009445 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009446 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009447 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009448 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009449 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009450 // for example, "bx lr"
9451 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009452 // bxj
9453 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009454 // compare and branch
9455 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009456 // table branch byte
9457 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9458 // table branch halfword
9459 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009460
9461 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009462 // Data-processing instructions
9463 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009464 // adc (immediate)
9465 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9466 // adc (register)
9467 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9468 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9469 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009470 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009471 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009472 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009473 // adr
9474 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9475 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9476 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009477 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009478 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009479 // and (register)
9480 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9481 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009482 // bic (immediate)
9483 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9484 // bic (register)
9485 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9486 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009487 // eor (immediate)
9488 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9489 // eor (register)
9490 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9491 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009492 // orr (immediate)
9493 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9494 // orr (register)
9495 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9496 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009497 // rsb (immediate)
9498 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9499 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9500 // rsb (register)
9501 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009502 // sbc (immediate)
9503 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9504 // sbc (register)
9505 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9506 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009507 // add (immediate, Thumb)
9508 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9509 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9510 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9511 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009512 // sub (immediate, Thumb)
9513 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9514 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9515 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9516 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009517 // sub (sp minus immediate)
9518 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9519 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009520 // teq (immediate)
9521 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9522 // teq (register)
9523 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009524 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009525 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009526 // tst (register)
9527 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9528 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9529
Johnny Chen7c5234d2011-02-18 23:41:11 +00009530
Johnny Chen338bf542011-02-10 19:29:03 +00009531 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009532 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009533 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009534 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009535 // mov{s}<c>.w <Rd>, <Rm>
9536 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009537 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009538 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9539 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Caroline Tice89c6d582011-03-29 19:53:44 +00009540 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009541 // mvn (immediate)
9542 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9543 // mvn (register)
9544 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9545 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009546 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009547 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009548 // cmn (register)
9549 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009550 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009551 // cmp (immediate)
9552 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009553 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009554 // cmp (register) (Rn and Rm both from r0-r7)
9555 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9556 // cmp (register) (Rn and Rm not both from r0-r7)
9557 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009558 // asr (immediate)
9559 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009560 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009561 // asr (register)
9562 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9563 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009564 // lsl (immediate)
9565 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9566 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9567 // lsl (register)
9568 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9569 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9570 // lsr (immediate)
9571 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9572 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9573 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009574 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009575 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009576 // rrx is a special case encoding of ror (immediate)
9577 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9578 // ror (immediate)
9579 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9580 // ror (register)
9581 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9582 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009583 // mul
9584 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9585 // mul
9586 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009587
Johnny Chen26863dc2011-02-09 23:43:29 +00009588 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009589 // Load instructions
9590 //----------------------------------------------------------------------
9591 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009592 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009593 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticebaf1f642011-03-24 19:23:45 +00009594 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9595 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
9596 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
9597 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
9598 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009599 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009600 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9601 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009602 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9603 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9604 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009605 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009606 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9607 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009608 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9609 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9610 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009611 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009612 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9613 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009614 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9615 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009616 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009617 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9618 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009619 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9620 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009621 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009622 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9623 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009624
9625 //----------------------------------------------------------------------
9626 // Store instructions
9627 //----------------------------------------------------------------------
9628 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009629 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009630 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009631 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9632 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9633 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9634 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9635 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9636 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9637 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9638 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009639 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009640 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9641 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009642
9643 //----------------------------------------------------------------------
9644 // Other instructions
9645 //----------------------------------------------------------------------
9646 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009647 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9648 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009649 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9650 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009651 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9652 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009653 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9654 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9655 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009656
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009657 };
9658
9659 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9660 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9661 {
9662 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9663 return &g_thumb_opcodes[i];
9664 }
9665 return NULL;
9666}
Greg Clayton64c84432011-01-21 22:02:52 +00009667
Greg Clayton31e2a382011-01-30 20:03:56 +00009668bool
Greg Clayton395fc332011-02-15 21:59:32 +00009669EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009670{
9671 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009672 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009673 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009674 {
Greg Clayton395fc332011-02-15 21:59:32 +00009675 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9676 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9677 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9678 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9679 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9680 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9681 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9682 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9683 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9684 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009685 }
9686 return m_arm_isa != 0;
9687}
9688
9689
Greg Clayton64c84432011-01-21 22:02:52 +00009690bool
9691EmulateInstructionARM::ReadInstruction ()
9692{
9693 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +00009694 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009695 if (success)
9696 {
9697 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9698 if (success)
9699 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009700 Context read_inst_context;
9701 read_inst_context.type = eContextReadOpcode;
9702 read_inst_context.SetNoArgs ();
9703
Greg Claytonb3448432011-03-24 21:19:54 +00009704 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +00009705 {
Greg Claytonb3448432011-03-24 21:19:54 +00009706 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009707 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009708
9709 if (success)
9710 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009711 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +00009712 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009713 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009714 }
9715 else
9716 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009717 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009718 }
9719 }
9720 }
9721 else
9722 {
Greg Claytonb3448432011-03-24 21:19:54 +00009723 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +00009724 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009725 }
9726 }
9727 }
9728 if (!success)
9729 {
Greg Claytonb3448432011-03-24 21:19:54 +00009730 m_opcode_mode = eModeInvalid;
9731 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +00009732 }
9733 return success;
9734}
9735
Johnny Chenee9b1f72011-02-09 01:00:31 +00009736uint32_t
9737EmulateInstructionARM::ArchVersion ()
9738{
9739 return m_arm_isa;
9740}
9741
Greg Clayton64c84432011-01-21 22:02:52 +00009742bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009743EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009744{
Greg Claytonb3448432011-03-24 21:19:54 +00009745 if (m_opcode_cpsr == 0)
Greg Clayton64c84432011-01-21 22:02:52 +00009746 return false;
9747
Greg Clayton7bc39082011-03-24 23:53:38 +00009748 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009749
9750 if (cond == UINT32_MAX)
9751 return false;
9752
9753 bool result = false;
9754 switch (UnsignedBits(cond, 3, 1))
9755 {
Greg Claytonb3448432011-03-24 21:19:54 +00009756 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
9757 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
9758 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
9759 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
9760 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 +00009761 case 5:
9762 {
Greg Claytonb3448432011-03-24 21:19:54 +00009763 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9764 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +00009765 result = n == v;
9766 }
9767 break;
9768 case 6:
9769 {
Greg Claytonb3448432011-03-24 21:19:54 +00009770 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9771 bool v = (m_opcode_cpsr & MASK_CPSR_V);
9772 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +00009773 }
9774 break;
9775 case 7:
9776 result = true;
9777 break;
9778 }
9779
9780 if (cond & 1)
9781 result = !result;
9782 return result;
9783}
9784
Johnny Chen9ee056b2011-02-08 00:06:35 +00009785uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +00009786EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009787{
Greg Claytonb3448432011-03-24 21:19:54 +00009788 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009789 {
9790 default:
9791 case eModeInvalid:
9792 break;
9793
9794 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +00009795 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009796
9797 case eModeThumb:
9798 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9799 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +00009800 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009801 const uint32_t byte_size = m_opcode.GetByteSize();
9802 if (byte_size == 2)
9803 {
9804 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
9805 return Bits32(opcode, 11, 7);
9806 }
9807 else
9808 {
9809 assert (byte_size == 4);
9810 if (Bits32(opcode, 31, 27) == 0x1e &&
9811 Bits32(opcode, 15, 14) == 0x02 &&
9812 Bits32(opcode, 12, 12) == 0x00 &&
9813 Bits32(opcode, 25, 22) <= 0x0d)
9814 {
9815 return Bits32(opcode, 25, 22);
9816 }
9817 }
9818
9819 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +00009820 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009821 }
9822 return UINT32_MAX; // Return invalid value
9823}
9824
Johnny Chen9ee056b2011-02-08 00:06:35 +00009825bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009826EmulateInstructionARM::InITBlock()
9827{
9828 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9829}
9830
9831bool
9832EmulateInstructionARM::LastInITBlock()
9833{
9834 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9835}
9836
Caroline Ticeb27771d2011-03-03 22:37:46 +00009837bool
9838EmulateInstructionARM::BadMode (uint32_t mode)
9839{
9840
9841 switch (mode)
9842 {
9843 case 16: return false; // '10000'
9844 case 17: return false; // '10001'
9845 case 18: return false; // '10010'
9846 case 19: return false; // '10011'
9847 case 22: return false; // '10110'
9848 case 23: return false; // '10111'
9849 case 27: return false; // '11011'
9850 case 31: return false; // '11111'
9851 default: return true;
9852 }
9853 return true;
9854}
9855
9856bool
9857EmulateInstructionARM::CurrentModeIsPrivileged ()
9858{
Greg Claytonb3448432011-03-24 21:19:54 +00009859 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009860
9861 if (BadMode (mode))
9862 return false;
9863
9864 if (mode == 16)
9865 return false;
9866
9867 return true;
9868}
9869
9870void
9871EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9872{
9873 bool privileged = CurrentModeIsPrivileged();
9874
9875 uint32_t tmp_cpsr = 0;
9876
Greg Claytonb3448432011-03-24 21:19:54 +00009877 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009878
9879 if (BitIsSet (bytemask, 3))
9880 {
9881 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
9882 if (affect_execstate)
9883 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
9884 }
9885
9886 if (BitIsSet (bytemask, 2))
9887 {
9888 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
9889 }
9890
9891 if (BitIsSet (bytemask, 1))
9892 {
9893 if (affect_execstate)
9894 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
9895 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
9896 if (privileged)
9897 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
9898 }
9899
9900 if (BitIsSet (bytemask, 0))
9901 {
9902 if (privileged)
9903 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
9904 if (affect_execstate)
9905 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
9906 if (privileged)
9907 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
9908 }
9909
Greg Claytonb3448432011-03-24 21:19:54 +00009910 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +00009911}
9912
9913
Johnny Chen098ae2d2011-02-12 00:50:05 +00009914bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009915EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9916{
9917 addr_t target;
9918
Johnny Chenee9b1f72011-02-09 01:00:31 +00009919 // Check the current instruction set.
9920 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009921 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009922 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009923 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009924
Johnny Chen9ee056b2011-02-08 00:06:35 +00009925 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009926 return false;
9927
9928 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009929}
9930
9931// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9932bool
Johnny Chen668b4512011-02-15 21:08:58 +00009933EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009934{
9935 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009936 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9937 // we want to record it and issue a WriteRegister callback so the clients
9938 // can track the mode changes accordingly.
9939 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009940
9941 if (BitIsSet(addr, 0))
9942 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009943 if (CurrentInstrSet() != eModeThumb)
9944 {
9945 SelectInstrSet(eModeThumb);
9946 cpsr_changed = true;
9947 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009948 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009949 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009950 }
9951 else if (BitIsClear(addr, 1))
9952 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009953 if (CurrentInstrSet() != eModeARM)
9954 {
9955 SelectInstrSet(eModeARM);
9956 cpsr_changed = true;
9957 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009958 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009959 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009960 }
9961 else
9962 return false; // address<1:0> == '10' => UNPREDICTABLE
9963
Johnny Chen0f309db2011-02-09 19:11:32 +00009964 if (cpsr_changed)
9965 {
Johnny Chen558133b2011-02-09 23:59:17 +00009966 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009967 return false;
9968 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009969 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009970 return false;
9971
9972 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009973}
Greg Clayton64c84432011-01-21 22:02:52 +00009974
Johnny Chenee9b1f72011-02-09 01:00:31 +00009975// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9976bool
Johnny Chen668b4512011-02-15 21:08:58 +00009977EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009978{
9979 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009980 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009981 else
9982 return BranchWritePC((const Context)context, addr);
9983}
9984
Johnny Chen26863dc2011-02-09 23:43:29 +00009985// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9986bool
Johnny Chen668b4512011-02-15 21:08:58 +00009987EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009988{
9989 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009990 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009991 else
9992 return BranchWritePC((const Context)context, addr);
9993}
9994
Johnny Chenee9b1f72011-02-09 01:00:31 +00009995EmulateInstructionARM::Mode
9996EmulateInstructionARM::CurrentInstrSet ()
9997{
Greg Claytonb3448432011-03-24 21:19:54 +00009998 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009999}
10000
Greg Claytonb3448432011-03-24 21:19:54 +000010001// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010002// ReadInstruction() is performed. This function has a side effect of updating
10003// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010004bool
10005EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10006{
Greg Claytonb3448432011-03-24 21:19:54 +000010007 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010008 switch (arm_or_thumb)
10009 {
10010 default:
10011 return false;
10012 eModeARM:
10013 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010014 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010015 break;
10016 eModeThumb:
10017 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010018 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010019 break;
10020 }
10021 return true;
10022}
10023
Johnny Chenef21b592011-02-10 01:52:38 +000010024// This function returns TRUE if the processor currently provides support for
10025// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10026// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10027bool
10028EmulateInstructionARM::UnalignedSupport()
10029{
10030 return (ArchVersion() >= ARMv7);
10031}
10032
Johnny Chenbf6ad172011-02-11 01:29:53 +000010033// The main addition and subtraction instructions can produce status information
10034// about both unsigned carry and signed overflow conditions. This status
10035// information can be used to synthesize multi-word additions and subtractions.
10036EmulateInstructionARM::AddWithCarryResult
10037EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10038{
10039 uint32_t result;
10040 uint8_t carry_out;
10041 uint8_t overflow;
10042
10043 uint64_t unsigned_sum = x + y + carry_in;
10044 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10045
10046 result = UnsignedBits(unsigned_sum, 31, 0);
10047 carry_out = (result == unsigned_sum ? 0 : 1);
10048 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10049
10050 AddWithCarryResult res = { result, carry_out, overflow };
10051 return res;
10052}
10053
Johnny Chen157b9592011-02-18 21:13:05 +000010054uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010055EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010056{
Johnny Chene39f22d2011-02-19 01:36:13 +000010057 uint32_t reg_kind, reg_num;
10058 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010059 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010060 case SP_REG:
10061 reg_kind = eRegisterKindGeneric;
10062 reg_num = LLDB_REGNUM_GENERIC_SP;
10063 break;
10064 case LR_REG:
10065 reg_kind = eRegisterKindGeneric;
10066 reg_num = LLDB_REGNUM_GENERIC_RA;
10067 break;
10068 case PC_REG:
10069 reg_kind = eRegisterKindGeneric;
10070 reg_num = LLDB_REGNUM_GENERIC_PC;
10071 break;
10072 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010073 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010074 {
10075 reg_kind = eRegisterKindDWARF;
10076 reg_num = dwarf_r0 + num;
10077 }
Johnny Chen157b9592011-02-18 21:13:05 +000010078 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010079 {
10080 assert(0 && "Invalid register number");
10081 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010082 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010083 }
10084 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010085 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010086
10087 // Read our register.
10088 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10089
10090 // When executing an ARM instruction , PC reads as the address of the current
10091 // instruction plus 8.
10092 // When executing a Thumb instruction , PC reads as the address of the current
10093 // instruction plus 4.
10094 if (num == 15)
10095 {
10096 if (CurrentInstrSet() == eModeARM)
10097 val += 8;
10098 else
10099 val += 4;
10100 }
Johnny Chen157b9592011-02-18 21:13:05 +000010101
10102 return val;
10103}
10104
Johnny Chenca67d1c2011-02-17 01:35:27 +000010105// Write the result to the ARM core register Rd, and optionally update the
10106// condition flags based on the result.
10107//
10108// This helper method tries to encapsulate the following pseudocode from the
10109// ARM Architecture Reference Manual:
10110//
10111// if d == 15 then // Can only occur for encoding A1
10112// ALUWritePC(result); // setflags is always FALSE here
10113// else
10114// R[d] = result;
10115// if setflags then
10116// APSR.N = result<31>;
10117// APSR.Z = IsZeroBit(result);
10118// APSR.C = carry;
10119// // APSR.V unchanged
10120//
10121// In the above case, the API client does not pass in the overflow arg, which
10122// defaults to ~0u.
10123bool
Johnny Chen10530c22011-02-17 22:37:12 +000010124EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10125 const uint32_t result,
10126 const uint32_t Rd,
10127 bool setflags,
10128 const uint32_t carry,
10129 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010130{
10131 if (Rd == 15)
10132 {
10133 if (!ALUWritePC (context, result))
10134 return false;
10135 }
10136 else
10137 {
Johnny Chena695f952011-02-23 21:24:25 +000010138 uint32_t reg_kind, reg_num;
10139 switch (Rd)
10140 {
10141 case SP_REG:
10142 reg_kind = eRegisterKindGeneric;
10143 reg_num = LLDB_REGNUM_GENERIC_SP;
10144 break;
10145 case LR_REG:
10146 reg_kind = eRegisterKindGeneric;
10147 reg_num = LLDB_REGNUM_GENERIC_RA;
10148 break;
10149 default:
10150 reg_kind = eRegisterKindDWARF;
10151 reg_num = dwarf_r0 + Rd;
10152 }
10153 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010154 return false;
10155 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010156 return WriteFlags (context, result, carry, overflow);
10157 }
10158 return true;
10159}
10160
10161// This helper method tries to encapsulate the following pseudocode from the
10162// ARM Architecture Reference Manual:
10163//
10164// APSR.N = result<31>;
10165// APSR.Z = IsZeroBit(result);
10166// APSR.C = carry;
10167// APSR.V = overflow
10168//
10169// Default arguments can be specified for carry and overflow parameters, which means
10170// not to update the respective flags.
10171bool
10172EmulateInstructionARM::WriteFlags (Context &context,
10173 const uint32_t result,
10174 const uint32_t carry,
10175 const uint32_t overflow)
10176{
Greg Claytonb3448432011-03-24 21:19:54 +000010177 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010178 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10179 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010180 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010181 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010182 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010183 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000010184 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000010185 {
10186 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10187 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010188 }
10189 return true;
10190}
10191
Greg Clayton64c84432011-01-21 22:02:52 +000010192bool
10193EmulateInstructionARM::EvaluateInstruction ()
10194{
Johnny Chenc315f862011-02-05 00:46:10 +000010195 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000010196 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000010197 m_it_session.ITAdvance();
10198
Greg Clayton64c84432011-01-21 22:02:52 +000010199 return false;
10200}