blob: 87813563c3fb286b8b3bd0fdb72d085d7c97767f [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) {
684 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000685 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000686 setflags = !InITBlock();
687 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000688 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000689 break;
690 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000691 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000692 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000693 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000694 if (BadReg(Rd))
695 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000696 break;
697 default:
698 return false;
699 }
700 uint32_t result = imm32;
701
702 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000703 EmulateInstruction::Context context;
704 context.type = EmulateInstruction::eContextImmediate;
705 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000706
Johnny Chen10530c22011-02-17 22:37:12 +0000707 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000708 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000709 }
710 return true;
711}
712
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000713// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
714// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
715// unsigned values.
716//
717// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
718// limited to only a few forms of the instruction.
719bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000720EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000721{
722#if 0
723 if ConditionPassed() then
724 EncodingSpecificOperations();
725 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
726 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
727 result = operand1 * operand2;
728 R[d] = result<31:0>;
729 if setflags then
730 APSR.N = result<31>;
731 APSR.Z = IsZeroBit(result);
732 if ArchVersion() == 4 then
733 APSR.C = bit UNKNOWN;
734 // else APSR.C unchanged
735 // APSR.V always unchanged
736#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000737
Greg Clayton7bc39082011-03-24 23:53:38 +0000738 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000739 {
740 uint32_t d;
741 uint32_t n;
742 uint32_t m;
743 bool setflags;
744
745 // EncodingSpecificOperations();
746 switch (encoding)
747 {
748 case eEncodingT1:
749 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
750 d = Bits32 (opcode, 2, 0);
751 n = Bits32 (opcode, 5, 3);
752 m = Bits32 (opcode, 2, 0);
753 setflags = !InITBlock();
754
755 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
756 if ((ArchVersion() < ARMv6) && (d == n))
757 return false;
758
759 break;
760
761 case eEncodingT2:
762 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
763 d = Bits32 (opcode, 11, 8);
764 n = Bits32 (opcode, 19, 16);
765 m = Bits32 (opcode, 3, 0);
766 setflags = false;
767
768 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
769 if (BadReg (d) || BadReg (n) || BadReg (m))
770 return false;
771
772 break;
773
774 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000775 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000776 d = Bits32 (opcode, 19, 16);
777 n = Bits32 (opcode, 3, 0);
778 m = Bits32 (opcode, 11, 8);
779 setflags = BitIsSet (opcode, 20);
780
781 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
782 if ((d == 15) || (n == 15) || (m == 15))
783 return false;
784
785 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
786 if ((ArchVersion() < ARMv6) && (d == n))
787 return false;
788
789 break;
790
791 default:
792 return false;
793 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000794
795 bool success = false;
796
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000797 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
798 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
799 if (!success)
800 return false;
801
802 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
803 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
804 if (!success)
805 return false;
806
807 // result = operand1 * operand2;
808 uint64_t result = operand1 * operand2;
809
810 // R[d] = result<31:0>;
811 Register op1_reg;
812 Register op2_reg;
813 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
814 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
815
816 EmulateInstruction::Context context;
817 context.type = eContextMultiplication;
818 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
819
820 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
821 return false;
822
823 // if setflags then
824 if (setflags)
825 {
826 // APSR.N = result<31>;
827 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000828 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000829 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
830 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000831 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000832 {
833 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
834 return false;
835 }
836
837 // if ArchVersion() == 4 then
838 // APSR.C = bit UNKNOWN;
839 }
840 }
841 return true;
842}
843
Johnny Chend642a6a2011-02-22 01:01:03 +0000844// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
845// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000846bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000847EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000848{
849#if 0
850 // ARM pseudo code...
851 if (ConditionPassed())
852 {
853 EncodingSpecificOperations();
854 result = NOT(imm32);
855 if d == 15 then // Can only occur for ARM encoding
856 ALUWritePC(result); // setflags is always FALSE here
857 else
858 R[d] = result;
859 if setflags then
860 APSR.N = result<31>;
861 APSR.Z = IsZeroBit(result);
862 APSR.C = carry;
863 // APSR.V unchanged
864 }
865#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000866
Greg Clayton7bc39082011-03-24 23:53:38 +0000867 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000868 {
869 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000870 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
871 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000872 bool setflags;
873 switch (encoding) {
874 case eEncodingT1:
875 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000876 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000877 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000878 break;
879 case eEncodingA1:
880 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000881 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000882 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
883 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
884 // TODO: Emulate SUBS PC, LR and related instructions.
885 if (Rd == 15 && setflags)
886 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000887 break;
888 default:
889 return false;
890 }
891 uint32_t result = ~imm32;
892
893 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000894 EmulateInstruction::Context context;
895 context.type = EmulateInstruction::eContextImmediate;
896 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000897
Johnny Chen10530c22011-02-17 22:37:12 +0000898 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000899 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000900 }
901 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000902}
903
Johnny Chend642a6a2011-02-22 01:01:03 +0000904// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
905// It can optionally update the condition flags based on the result.
906bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000907EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +0000908{
909#if 0
910 // ARM pseudo code...
911 if (ConditionPassed())
912 {
913 EncodingSpecificOperations();
914 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
915 result = NOT(shifted);
916 if d == 15 then // Can only occur for ARM encoding
917 ALUWritePC(result); // setflags is always FALSE here
918 else
919 R[d] = result;
920 if setflags then
921 APSR.N = result<31>;
922 APSR.Z = IsZeroBit(result);
923 APSR.C = carry;
924 // APSR.V unchanged
925 }
926#endif
927
Greg Clayton7bc39082011-03-24 23:53:38 +0000928 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +0000929 {
930 uint32_t Rm; // the source register
931 uint32_t Rd; // the destination register
932 ARM_ShifterType shift_t;
933 uint32_t shift_n; // the shift applied to the value read from Rm
934 bool setflags;
935 uint32_t carry; // the carry bit after the shift operation
936 switch (encoding) {
937 case eEncodingT1:
938 Rd = Bits32(opcode, 2, 0);
939 Rm = Bits32(opcode, 5, 3);
940 setflags = !InITBlock();
941 shift_t = SRType_LSL;
942 shift_n = 0;
943 if (InITBlock())
944 return false;
945 break;
946 case eEncodingT2:
947 Rd = Bits32(opcode, 11, 8);
948 Rm = Bits32(opcode, 3, 0);
949 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000950 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000951 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000952 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000953 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000954 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000955 case eEncodingA1:
956 Rd = Bits32(opcode, 15, 12);
957 Rm = Bits32(opcode, 3, 0);
958 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000959 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000960 break;
961 default:
962 return false;
963 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000964 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +0000965 uint32_t value = ReadCoreReg(Rm, &success);
966 if (!success)
967 return false;
968
969 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
970 uint32_t result = ~shifted;
971
972 // The context specifies that an immediate is to be moved into Rd.
973 EmulateInstruction::Context context;
974 context.type = EmulateInstruction::eContextImmediate;
975 context.SetNoArgs ();
976
977 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
978 return false;
979 }
980 return true;
981}
982
Johnny Chen788e0552011-01-27 22:52:23 +0000983// PC relative immediate load into register, possibly followed by ADD (SP plus register).
984// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000985bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000986EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000987{
988#if 0
989 // ARM pseudo code...
990 if (ConditionPassed())
991 {
992 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
993 base = Align(PC,4);
994 address = if add then (base + imm32) else (base - imm32);
995 data = MemU[address,4];
996 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000997 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
998 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +0000999 R[t] = data;
1000 else // Can only apply before ARMv7
1001 if CurrentInstrSet() == InstrSet_ARM then
1002 R[t] = ROR(data, 8*UInt(address<1:0>));
1003 else
1004 R[t] = bits(32) UNKNOWN;
1005 }
1006#endif
1007
Greg Clayton7bc39082011-03-24 23:53:38 +00001008 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001009 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001010 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001011 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001012 if (!success)
1013 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001014
1015 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001016 EmulateInstruction::Context context;
1017 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1018 Register pc_reg;
1019 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1020 context.SetRegisterPlusOffset (pc_reg, 0);
1021
Johnny Chenc9de9102011-02-11 19:12:30 +00001022 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001023 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001024 bool add; // +imm32 or -imm32?
1025 addr_t base; // the base address
1026 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001027 uint32_t data; // the literal data value from the PC relative load
1028 switch (encoding) {
1029 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001030 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001031 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001032 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001033 break;
1034 case eEncodingT2:
1035 Rt = Bits32(opcode, 15, 12);
1036 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1037 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001038 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001039 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001040 break;
1041 default:
1042 return false;
1043 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001044
Johnny Chene39f22d2011-02-19 01:36:13 +00001045 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001046 if (add)
1047 address = base + imm32;
1048 else
1049 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001050
1051 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001052 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001053 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001054 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001055
1056 if (Rt == 15)
1057 {
1058 if (Bits32(address, 1, 0) == 0)
1059 {
1060 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001061 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001062 return false;
1063 }
1064 else
1065 return false;
1066 }
1067 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1068 {
1069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1070 return false;
1071 }
1072 else // We don't handle ARM for now.
1073 return false;
1074
Johnny Chen788e0552011-01-27 22:52:23 +00001075 }
1076 return true;
1077}
1078
Johnny Chen5b442b72011-01-27 19:34:30 +00001079// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001080// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001081bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001082EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001083{
1084#if 0
1085 // ARM pseudo code...
1086 if (ConditionPassed())
1087 {
1088 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001089 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001090 if d == 15 then // Can only occur for ARM encoding
1091 ALUWritePC(result); // setflags is always FALSE here
1092 else
1093 R[d] = result;
1094 if setflags then
1095 APSR.N = result<31>;
1096 APSR.Z = IsZeroBit(result);
1097 APSR.C = carry;
1098 APSR.V = overflow;
1099 }
1100#endif
1101
1102 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001103
Greg Clayton7bc39082011-03-24 23:53:38 +00001104 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001105 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001106 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001107 if (!success)
1108 return false;
1109 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001110 uint32_t d;
1111 bool setflags;
1112 switch (encoding)
1113 {
1114 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001115 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001116 d = Bits32 (opcode, 10, 8);
1117 setflags = false;
1118 imm32 = (Bits32 (opcode, 7, 0) << 2);
1119
1120 break;
1121
1122 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001123 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001124 d = 13;
1125 setflags = false;
1126 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1127
1128 break;
1129
1130 default:
1131 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001132 }
1133 addr_t sp_offset = imm32;
1134 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1135
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001136 EmulateInstruction::Context context;
1137 context.type = EmulateInstruction::eContextAdjustStackPointer;
1138 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001139
Caroline Ticee2212882011-03-22 22:38:28 +00001140 if (d == 15)
1141 {
1142 if (!ALUWritePC (context, addr))
1143 return false;
1144 }
1145 else
1146 {
1147 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1148 return false;
1149 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001150 }
1151 return true;
1152}
1153
1154// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001155// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001156bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001157EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001158{
1159#if 0
1160 // ARM pseudo code...
1161 if (ConditionPassed())
1162 {
1163 EncodingSpecificOperations();
1164 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001165 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001166 if d == 15 then
1167 ALUWritePC(result); // setflags is always FALSE here
1168 else
1169 R[d] = result;
1170 if setflags then
1171 APSR.N = result<31>;
1172 APSR.Z = IsZeroBit(result);
1173 APSR.C = carry;
1174 APSR.V = overflow;
1175 }
1176#endif
1177
1178 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001179
Greg Clayton7bc39082011-03-24 23:53:38 +00001180 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001181 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001182 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001183 if (!success)
1184 return false;
1185 uint32_t Rm; // the second operand
1186 switch (encoding) {
1187 case eEncodingT2:
1188 Rm = Bits32(opcode, 6, 3);
1189 break;
1190 default:
1191 return false;
1192 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001193 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001194 if (!success)
1195 return false;
1196
1197 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1198
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001199 EmulateInstruction::Context context;
1200 context.type = EmulateInstruction::eContextAdjustStackPointer;
1201 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001202
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001203 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001204 return false;
1205 }
1206 return true;
1207}
1208
Johnny Chen9b8d7832011-02-02 01:13:56 +00001209// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1210// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1211// from Thumb to ARM.
1212// BLX (immediate)
1213bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001214EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001215{
1216#if 0
1217 // ARM pseudo code...
1218 if (ConditionPassed())
1219 {
1220 EncodingSpecificOperations();
1221 if CurrentInstrSet() == InstrSet_ARM then
1222 LR = PC - 4;
1223 else
1224 LR = PC<31:1> : '1';
1225 if targetInstrSet == InstrSet_ARM then
1226 targetAddress = Align(PC,4) + imm32;
1227 else
1228 targetAddress = PC + imm32;
1229 SelectInstrSet(targetInstrSet);
1230 BranchWritePC(targetAddress);
1231 }
1232#endif
1233
Greg Clayton7bc39082011-03-24 23:53:38 +00001234 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001235
Greg Clayton7bc39082011-03-24 23:53:38 +00001236 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001237 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001238 EmulateInstruction::Context context;
1239 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001240 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001241 if (!success)
1242 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001243 addr_t lr; // next instruction address
1244 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001245 int32_t imm32; // PC-relative offset
1246 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001247 case eEncodingT1:
1248 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001249 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001250 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001251 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001252 uint32_t J1 = Bit32(opcode, 13);
1253 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001254 uint32_t imm11 = Bits32(opcode, 10, 0);
1255 uint32_t I1 = !(J1 ^ S);
1256 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001257 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001258 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001259 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001260 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001261 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001262 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001263 break;
1264 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001265 case eEncodingT2:
1266 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001267 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001268 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001269 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001270 uint32_t J1 = Bit32(opcode, 13);
1271 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001272 uint32_t imm10L = Bits32(opcode, 10, 1);
1273 uint32_t I1 = !(J1 ^ S);
1274 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001275 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001276 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001277 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001278 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001279 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001280 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001281 break;
1282 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001283 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001284 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001285 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001286 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001287 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001288 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001290 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001292 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001293 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001294 break;
1295 default:
1296 return false;
1297 }
1298 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1299 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001300 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001301 return false;
1302 }
1303 return true;
1304}
1305
1306// Branch with Link and Exchange (register) calls a subroutine at an address and
1307// instruction set specified by a register.
1308// BLX (register)
1309bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001310EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311{
1312#if 0
1313 // ARM pseudo code...
1314 if (ConditionPassed())
1315 {
1316 EncodingSpecificOperations();
1317 target = R[m];
1318 if CurrentInstrSet() == InstrSet_ARM then
1319 next_instr_addr = PC - 4;
1320 LR = next_instr_addr;
1321 else
1322 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001323 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001324 BXWritePC(target);
1325 }
1326#endif
1327
1328 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001329
Greg Clayton7bc39082011-03-24 23:53:38 +00001330 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001331 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001332 EmulateInstruction::Context context;
1333 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001334 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001335 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001336 if (!success)
1337 return false;
1338 uint32_t Rm; // the register with the target address
1339 switch (encoding) {
1340 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001341 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001342 Rm = Bits32(opcode, 6, 3);
1343 // if m == 15 then UNPREDICTABLE;
1344 if (Rm == 15)
1345 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001346 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001347 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001348 break;
1349 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001350 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001351 Rm = Bits32(opcode, 3, 0);
1352 // if m == 15 then UNPREDICTABLE;
1353 if (Rm == 15)
1354 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001355 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 default:
1357 return false;
1358 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001359 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001360 if (!success)
1361 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001362 Register dwarf_reg;
1363 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1364 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001365 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1366 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001367 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001368 return false;
1369 }
1370 return true;
1371}
1372
Johnny Chenab3b3512011-02-12 00:10:51 +00001373// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001374bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001375EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001376{
1377#if 0
1378 // ARM pseudo code...
1379 if (ConditionPassed())
1380 {
1381 EncodingSpecificOperations();
1382 BXWritePC(R[m]);
1383 }
1384#endif
1385
Greg Clayton7bc39082011-03-24 23:53:38 +00001386 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001387 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001388 EmulateInstruction::Context context;
1389 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001390 uint32_t Rm; // the register with the target address
1391 switch (encoding) {
1392 case eEncodingT1:
1393 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001394 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001395 return false;
1396 break;
1397 case eEncodingA1:
1398 Rm = Bits32(opcode, 3, 0);
1399 break;
1400 default:
1401 return false;
1402 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001403 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001404 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001405 if (!success)
1406 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001407
1408 Register dwarf_reg;
1409 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001410 context.SetRegister (dwarf_reg);
1411 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001412 return false;
1413 }
1414 return true;
1415}
1416
Johnny Chen59e6ab72011-02-24 21:01:20 +00001417// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1418// address and instruction set specified by a register as though it were a BX instruction.
1419//
1420// TODO: Emulate Jazelle architecture?
1421// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1422bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001423EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001424{
1425#if 0
1426 // ARM pseudo code...
1427 if (ConditionPassed())
1428 {
1429 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001430 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001431 BXWritePC(R[m]);
1432 else
1433 if JazelleAcceptsExecution() then
1434 SwitchToJazelleExecution();
1435 else
1436 SUBARCHITECTURE_DEFINED handler call;
1437 }
1438#endif
1439
Greg Clayton7bc39082011-03-24 23:53:38 +00001440 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001441 {
1442 EmulateInstruction::Context context;
1443 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1444 uint32_t Rm; // the register with the target address
1445 switch (encoding) {
1446 case eEncodingT1:
1447 Rm = Bits32(opcode, 19, 16);
1448 if (BadReg(Rm))
1449 return false;
1450 if (InITBlock() && !LastInITBlock())
1451 return false;
1452 break;
1453 case eEncodingA1:
1454 Rm = Bits32(opcode, 3, 0);
1455 if (Rm == 15)
1456 return false;
1457 break;
1458 default:
1459 return false;
1460 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001461 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001462 addr_t target = ReadCoreReg (Rm, &success);
1463 if (!success)
1464 return false;
1465
1466 Register dwarf_reg;
1467 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1468 context.SetRegister (dwarf_reg);
1469 if (!BXWritePC(context, target))
1470 return false;
1471 }
1472 return true;
1473}
1474
Johnny Chen0d0148e2011-01-28 02:26:08 +00001475// Set r7 to point to some ip offset.
1476// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001477bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001478EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001479{
1480#if 0
1481 // ARM pseudo code...
1482 if (ConditionPassed())
1483 {
1484 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001485 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001486 if d == 15 then // Can only occur for ARM encoding
1487 ALUWritePC(result); // setflags is always FALSE here
1488 else
1489 R[d] = result;
1490 if setflags then
1491 APSR.N = result<31>;
1492 APSR.Z = IsZeroBit(result);
1493 APSR.C = carry;
1494 APSR.V = overflow;
1495 }
1496#endif
1497
Greg Clayton7bc39082011-03-24 23:53:38 +00001498 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001499 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001500 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001501 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001502 if (!success)
1503 return false;
1504 uint32_t imm32;
1505 switch (encoding) {
1506 case eEncodingA1:
1507 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1508 break;
1509 default:
1510 return false;
1511 }
1512 addr_t ip_offset = imm32;
1513 addr_t addr = ip - ip_offset; // the adjusted ip value
1514
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001515 EmulateInstruction::Context context;
1516 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1517 Register dwarf_reg;
1518 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1519 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001522 return false;
1523 }
1524 return true;
1525}
1526
1527// Set ip to point to some stack offset.
1528// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001529bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001530EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001531{
1532#if 0
1533 // ARM pseudo code...
1534 if (ConditionPassed())
1535 {
1536 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001537 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001538 if d == 15 then // Can only occur for ARM encoding
1539 ALUWritePC(result); // setflags is always FALSE here
1540 else
1541 R[d] = result;
1542 if setflags then
1543 APSR.N = result<31>;
1544 APSR.Z = IsZeroBit(result);
1545 APSR.C = carry;
1546 APSR.V = overflow;
1547 }
1548#endif
1549
Greg Clayton7bc39082011-03-24 23:53:38 +00001550 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001551 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001552 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001553 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001554 if (!success)
1555 return false;
1556 uint32_t imm32;
1557 switch (encoding) {
1558 case eEncodingA1:
1559 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1560 break;
1561 default:
1562 return false;
1563 }
1564 addr_t sp_offset = imm32;
1565 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1566
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001567 EmulateInstruction::Context context;
1568 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1569 Register dwarf_reg;
1570 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1571 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001572
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001573 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001574 return false;
1575 }
1576 return true;
1577}
1578
Johnny Chenc9e747f2011-02-23 01:55:07 +00001579// This instruction subtracts an immediate value from the SP value, and writes
1580// the result to the destination register.
1581//
1582// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001583bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001584EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001585{
1586#if 0
1587 // ARM pseudo code...
1588 if (ConditionPassed())
1589 {
1590 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001591 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001592 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001593 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001594 else
1595 R[d] = result;
1596 if setflags then
1597 APSR.N = result<31>;
1598 APSR.Z = IsZeroBit(result);
1599 APSR.C = carry;
1600 APSR.V = overflow;
1601 }
1602#endif
1603
1604 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001605 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001606 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001607 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001608 if (!success)
1609 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001610
1611 uint32_t Rd;
1612 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001613 uint32_t imm32;
1614 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001615 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001616 Rd = 13;
1617 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001618 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001619 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001620 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001621 Rd = Bits32(opcode, 11, 8);
1622 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001623 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001624 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001625 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001626 if (Rd == 15 && !setflags)
1627 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001628 break;
1629 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001630 Rd = Bits32(opcode, 11, 8);
1631 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001632 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001633 if (Rd == 15)
1634 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001635 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001636 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001637 Rd = Bits32(opcode, 15, 12);
1638 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001639 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001640 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1641 // TODO: Emulate SUBS PC, LR and related instructions.
1642 if (Rd == 15 && setflags)
1643 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001644 break;
1645 default:
1646 return false;
1647 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001648 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1649
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001650 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001651 if (Rd == 13)
1652 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001653 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1654 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001655 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001656 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001657 }
1658 else
1659 {
1660 context.type = EmulateInstruction::eContextImmediate;
1661 context.SetNoArgs ();
1662 }
1663
1664 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001665 return false;
1666 }
1667 return true;
1668}
1669
Johnny Chen08c25e82011-01-31 18:02:28 +00001670// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001671bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001672EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001673{
1674#if 0
1675 // ARM pseudo code...
1676 if (ConditionPassed())
1677 {
1678 EncodingSpecificOperations();
1679 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1680 address = if index then offset_addr else R[n];
1681 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1682 if wback then R[n] = offset_addr;
1683 }
1684#endif
1685
1686 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001687
Greg Clayton7bc39082011-03-24 23:53:38 +00001688 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001689 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001690 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001691 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001692 if (!success)
1693 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001694 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001695 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001696 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1697
1698 bool index;
1699 bool add;
1700 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001701 switch (encoding) {
1702 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001703 Rt = Bits32(opcode, 15, 12);
1704 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001705 Rn = Bits32 (opcode, 19, 16);
1706
1707 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1708 return false;
1709
1710 index = BitIsSet (opcode, 24);
1711 add = BitIsSet (opcode, 23);
1712 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1713
1714 if (wback && ((Rn == 15) || (Rn == Rt)))
1715 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001716 break;
1717 default:
1718 return false;
1719 }
Caroline Tice3e407972011-03-18 19:41:00 +00001720 addr_t offset_addr;
1721 if (add)
1722 offset_addr = sp + imm12;
1723 else
1724 offset_addr = sp - imm12;
1725
1726 addr_t addr;
1727 if (index)
1728 addr = offset_addr;
1729 else
1730 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001731
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001732 EmulateInstruction::Context context;
1733 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001734 Register sp_reg;
1735 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1736 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001737 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001738 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001739 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001740 if (!success)
1741 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001742 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001743 return false;
1744 }
1745 else
1746 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001747 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001748 if (!success)
1749 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001750 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001751 return false;
1752 }
1753
Caroline Tice3e407972011-03-18 19:41:00 +00001754
1755 if (wback)
1756 {
1757 context.type = EmulateInstruction::eContextAdjustStackPointer;
1758 context.SetImmediateSigned (addr - sp);
1759 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1760 return false;
1761 }
Johnny Chence1ca772011-01-25 01:13:00 +00001762 }
1763 return true;
1764}
1765
Johnny Chen08c25e82011-01-31 18:02:28 +00001766// Vector Push stores multiple extension registers to the stack.
1767// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001769EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001770{
1771#if 0
1772 // ARM pseudo code...
1773 if (ConditionPassed())
1774 {
1775 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1776 address = SP - imm32;
1777 SP = SP - imm32;
1778 if single_regs then
1779 for r = 0 to regs-1
1780 MemA[address,4] = S[d+r]; address = address+4;
1781 else
1782 for r = 0 to regs-1
1783 // Store as two word-aligned words in the correct order for current endianness.
1784 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1785 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1786 address = address+8;
1787 }
1788#endif
1789
1790 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001791
Greg Clayton7bc39082011-03-24 23:53:38 +00001792 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001793 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001794 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001795 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001796 if (!success)
1797 return false;
1798 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001799 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001800 uint32_t imm32; // stack offset
1801 uint32_t regs; // number of registers
1802 switch (encoding) {
1803 case eEncodingT1:
1804 case eEncodingA1:
1805 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001806 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001807 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1808 // If UInt(imm8) is odd, see "FSTMX".
1809 regs = Bits32(opcode, 7, 0) / 2;
1810 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1811 if (regs == 0 || regs > 16 || (d + regs) > 32)
1812 return false;
1813 break;
1814 case eEncodingT2:
1815 case eEncodingA2:
1816 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001817 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001818 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1819 regs = Bits32(opcode, 7, 0);
1820 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1821 if (regs == 0 || regs > 16 || (d + regs) > 32)
1822 return false;
1823 break;
1824 default:
1825 return false;
1826 }
1827 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1828 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1829 addr_t sp_offset = imm32;
1830 addr_t addr = sp - sp_offset;
1831 uint32_t i;
1832
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001833 EmulateInstruction::Context context;
1834 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1835 Register dwarf_reg;
1836 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001837 Register sp_reg;
1838 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1839 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001840 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001841 dwarf_reg.num = start_reg + d + i;
1842 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001843 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001844 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001845 if (!success)
1846 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001847 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001848 return false;
1849 addr += reg_byte_size;
1850 }
1851
1852 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001853 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001854
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001855 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001856 return false;
1857 }
1858 return true;
1859}
1860
Johnny Chen587a0a42011-02-01 18:35:28 +00001861// Vector Pop loads multiple extension registers from the stack.
1862// It also updates SP to point just above the loaded data.
1863bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001864EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001865{
1866#if 0
1867 // ARM pseudo code...
1868 if (ConditionPassed())
1869 {
1870 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1871 address = SP;
1872 SP = SP + imm32;
1873 if single_regs then
1874 for r = 0 to regs-1
1875 S[d+r] = MemA[address,4]; address = address+4;
1876 else
1877 for r = 0 to regs-1
1878 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1879 // Combine the word-aligned words in the correct order for current endianness.
1880 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1881 }
1882#endif
1883
1884 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001885
Greg Clayton7bc39082011-03-24 23:53:38 +00001886 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001887 {
1888 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001889 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001890 if (!success)
1891 return false;
1892 bool single_regs;
1893 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1894 uint32_t imm32; // stack offset
1895 uint32_t regs; // number of registers
1896 switch (encoding) {
1897 case eEncodingT1:
1898 case eEncodingA1:
1899 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001900 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001901 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1902 // If UInt(imm8) is odd, see "FLDMX".
1903 regs = Bits32(opcode, 7, 0) / 2;
1904 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1905 if (regs == 0 || regs > 16 || (d + regs) > 32)
1906 return false;
1907 break;
1908 case eEncodingT2:
1909 case eEncodingA2:
1910 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001911 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001912 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1913 regs = Bits32(opcode, 7, 0);
1914 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1915 if (regs == 0 || regs > 16 || (d + regs) > 32)
1916 return false;
1917 break;
1918 default:
1919 return false;
1920 }
1921 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1922 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1923 addr_t sp_offset = imm32;
1924 addr_t addr = sp;
1925 uint32_t i;
1926 uint64_t data; // uint64_t to accomodate 64-bit registers.
1927
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001928 EmulateInstruction::Context context;
1929 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1930 Register dwarf_reg;
1931 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001932 Register sp_reg;
1933 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1934 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00001935 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001936 dwarf_reg.num = start_reg + d + i;
1937 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001938 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001939 if (!success)
1940 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001941 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001942 return false;
1943 addr += reg_byte_size;
1944 }
1945
1946 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001947 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001948
1949 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1950 return false;
1951 }
1952 return true;
1953}
1954
Johnny Chenb77be412011-02-04 00:40:18 +00001955// SVC (previously SWI)
1956bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001957EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00001958{
1959#if 0
1960 // ARM pseudo code...
1961 if (ConditionPassed())
1962 {
1963 EncodingSpecificOperations();
1964 CallSupervisor();
1965 }
1966#endif
1967
1968 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00001969
Greg Clayton7bc39082011-03-24 23:53:38 +00001970 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00001971 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001972 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001973 addr_t lr; // next instruction address
1974 if (!success)
1975 return false;
1976 uint32_t imm32; // the immediate constant
1977 uint32_t mode; // ARM or Thumb mode
1978 switch (encoding) {
1979 case eEncodingT1:
1980 lr = (pc + 2) | 1u; // return address
1981 imm32 = Bits32(opcode, 7, 0);
1982 mode = eModeThumb;
1983 break;
1984 case eEncodingA1:
1985 lr = pc + 4; // return address
1986 imm32 = Bits32(opcode, 23, 0);
1987 mode = eModeARM;
1988 break;
1989 default:
1990 return false;
1991 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001992
1993 EmulateInstruction::Context context;
1994 context.type = EmulateInstruction::eContextSupervisorCall;
1995 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001996 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1997 return false;
1998 }
1999 return true;
2000}
2001
Johnny Chenc315f862011-02-05 00:46:10 +00002002// If Then makes up to four following instructions (the IT block) conditional.
2003bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002004EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002005{
2006#if 0
2007 // ARM pseudo code...
2008 EncodingSpecificOperations();
2009 ITSTATE.IT<7:0> = firstcond:mask;
2010#endif
2011
Johnny Chenc315f862011-02-05 00:46:10 +00002012 m_it_session.InitIT(Bits32(opcode, 7, 0));
2013 return true;
2014}
2015
Johnny Chen3b620b32011-02-07 20:11:47 +00002016// Branch causes a branch to a target address.
2017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002018EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002019{
2020#if 0
2021 // ARM pseudo code...
2022 if (ConditionPassed())
2023 {
2024 EncodingSpecificOperations();
2025 BranchWritePC(PC + imm32);
2026 }
2027#endif
2028
2029 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002030
Greg Clayton7bc39082011-03-24 23:53:38 +00002031 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002032 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002033 EmulateInstruction::Context context;
2034 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002035 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002036 if (!success)
2037 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002038 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002039 int32_t imm32; // PC-relative offset
2040 switch (encoding) {
2041 case eEncodingT1:
2042 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2043 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002044 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002045 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002046 break;
2047 case eEncodingT2:
2048 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002049 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002050 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002051 break;
2052 case eEncodingT3:
2053 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2054 {
Johnny Chenbd599902011-02-10 21:39:01 +00002055 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002056 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002057 uint32_t J1 = Bit32(opcode, 13);
2058 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002059 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002060 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002061 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002062 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002063 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002064 break;
2065 }
2066 case eEncodingT4:
2067 {
Johnny Chenbd599902011-02-10 21:39:01 +00002068 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002069 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002070 uint32_t J1 = Bit32(opcode, 13);
2071 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002072 uint32_t imm11 = Bits32(opcode, 10, 0);
2073 uint32_t I1 = !(J1 ^ S);
2074 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002075 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002076 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002077 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002078 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002079 break;
2080 }
2081 case eEncodingA1:
2082 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002083 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002084 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002085 break;
2086 default:
2087 return false;
2088 }
2089 if (!BranchWritePC(context, target))
2090 return false;
2091 }
2092 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002093}
2094
Johnny Chen53ebab72011-02-08 23:21:57 +00002095// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2096// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2097// CBNZ, CBZ
2098bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002099EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002100{
2101#if 0
2102 // ARM pseudo code...
2103 EncodingSpecificOperations();
2104 if nonzero ^ IsZero(R[n]) then
2105 BranchWritePC(PC + imm32);
2106#endif
2107
2108 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002109
2110 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002111 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002112 if (!success)
2113 return false;
2114
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002115 EmulateInstruction::Context context;
2116 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002117 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002118 if (!success)
2119 return false;
2120
2121 addr_t target; // target address
2122 uint32_t imm32; // PC-relative offset to branch forward
2123 bool nonzero;
2124 switch (encoding) {
2125 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002126 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002127 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002128 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002129 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002130 break;
2131 default:
2132 return false;
2133 }
2134 if (nonzero ^ (reg_val == 0))
2135 if (!BranchWritePC(context, target))
2136 return false;
2137
2138 return true;
2139}
2140
Johnny Chen60299ec2011-02-17 19:34:27 +00002141// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2142// A base register provides a pointer to the table, and a second register supplies an index into the table.
2143// The branch length is twice the value of the byte returned from the table.
2144//
2145// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2146// A base register provides a pointer to the table, and a second register supplies an index into the table.
2147// The branch length is twice the value of the halfword returned from the table.
2148// TBB, TBH
2149bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002150EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002151{
2152#if 0
2153 // ARM pseudo code...
2154 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2155 if is_tbh then
2156 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2157 else
2158 halfwords = UInt(MemU[R[n]+R[m], 1]);
2159 BranchWritePC(PC + 2*halfwords);
2160#endif
2161
2162 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002163
2164 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2165 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2166 bool is_tbh; // true if table branch halfword
2167 switch (encoding) {
2168 case eEncodingT1:
2169 Rn = Bits32(opcode, 19, 16);
2170 Rm = Bits32(opcode, 3, 0);
2171 is_tbh = BitIsSet(opcode, 4);
2172 if (Rn == 13 || BadReg(Rm))
2173 return false;
2174 if (InITBlock() && !LastInITBlock())
2175 return false;
2176 break;
2177 default:
2178 return false;
2179 }
2180
2181 // Read the address of the table from the operand register Rn.
2182 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002183 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002184 if (!success)
2185 return false;
2186
2187 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002188 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002189 if (!success)
2190 return false;
2191
2192 // the offsetted table address
2193 addr_t addr = base + (is_tbh ? index*2 : index);
2194
2195 // PC-relative offset to branch forward
2196 EmulateInstruction::Context context;
2197 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002198 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002199 if (!success)
2200 return false;
2201
Johnny Chene39f22d2011-02-19 01:36:13 +00002202 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002203 if (!success)
2204 return false;
2205
2206 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002207 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002208 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2209 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2210
2211 if (!BranchWritePC(context, target))
2212 return false;
2213
2214 return true;
2215}
2216
Caroline Ticedcc11b32011-03-02 23:57:02 +00002217// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2218// It can optionally update the condition flags based on the result.
2219bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002220EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002221{
2222#if 0
2223 if ConditionPassed() then
2224 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002225 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002226 R[d] = result;
2227 if setflags then
2228 APSR.N = result<31>;
2229 APSR.Z = IsZeroBit(result);
2230 APSR.C = carry;
2231 APSR.V = overflow;
2232#endif
2233
2234 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002235
Greg Clayton7bc39082011-03-24 23:53:38 +00002236 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002237 {
2238 uint32_t d;
2239 uint32_t n;
2240 bool setflags;
2241 uint32_t imm32;
2242 uint32_t carry_out;
2243
2244 //EncodingSpecificOperations();
2245 switch (encoding)
2246 {
2247 case eEncodingT1:
2248 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2249 d = Bits32 (opcode, 2, 0);
2250 n = Bits32 (opcode, 5, 3);
2251 setflags = !InITBlock();
2252 imm32 = Bits32 (opcode, 8,6);
2253
2254 break;
2255
2256 case eEncodingT2:
2257 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2258 d = Bits32 (opcode, 10, 8);
2259 n = Bits32 (opcode, 10, 8);
2260 setflags = !InITBlock();
2261 imm32 = Bits32 (opcode, 7, 0);
2262
2263 break;
2264
2265 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002266 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2267 // if Rn == '1101' then SEE ADD (SP plus immediate);
2268 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002269 d = Bits32 (opcode, 11, 8);
2270 n = Bits32 (opcode, 19, 16);
2271 setflags = BitIsSet (opcode, 20);
2272 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2273
2274 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2275 if (BadReg (d) || (n == 15))
2276 return false;
2277
2278 break;
2279
2280 case eEncodingT4:
2281 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002282 // if Rn == '1111' then SEE ADR;
2283 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002284 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2285 d = Bits32 (opcode, 11, 8);
2286 n = Bits32 (opcode, 19, 16);
2287 setflags = false;
2288 uint32_t i = Bit32 (opcode, 26);
2289 uint32_t imm3 = Bits32 (opcode, 14, 12);
2290 uint32_t imm8 = Bits32 (opcode, 7, 0);
2291 imm32 = (i << 11) | (imm3 << 8) | imm8;
2292
2293 // if BadReg(d) then UNPREDICTABLE;
2294 if (BadReg (d))
2295 return false;
2296
2297 break;
2298 }
2299 default:
2300 return false;
2301 }
2302
2303 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2304 if (!success)
2305 return false;
2306
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002307 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002308 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2309
2310 Register reg_n;
2311 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2312
2313 EmulateInstruction::Context context;
2314 context.type = eContextAddition;
2315 context.SetRegisterPlusOffset (reg_n, imm32);
2316
2317 //R[d] = result;
2318 //if setflags then
2319 //APSR.N = result<31>;
2320 //APSR.Z = IsZeroBit(result);
2321 //APSR.C = carry;
2322 //APSR.V = overflow;
2323 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2324 return false;
2325
2326 }
2327 return true;
2328}
2329
Johnny Chen8fa20592011-02-18 01:22:22 +00002330// This instruction adds an immediate value to a register value, and writes the result to the destination
2331// register. It can optionally update the condition flags based on the result.
2332bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002333EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002334{
2335#if 0
2336 // ARM pseudo code...
2337 if ConditionPassed() then
2338 EncodingSpecificOperations();
2339 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2340 if d == 15 then
2341 ALUWritePC(result); // setflags is always FALSE here
2342 else
2343 R[d] = result;
2344 if setflags then
2345 APSR.N = result<31>;
2346 APSR.Z = IsZeroBit(result);
2347 APSR.C = carry;
2348 APSR.V = overflow;
2349#endif
2350
2351 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002352
Greg Clayton7bc39082011-03-24 23:53:38 +00002353 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002354 {
2355 uint32_t Rd, Rn;
2356 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2357 bool setflags;
2358 switch (encoding)
2359 {
2360 case eEncodingA1:
2361 Rd = Bits32(opcode, 15, 12);
2362 Rn = Bits32(opcode, 19, 16);
2363 setflags = BitIsSet(opcode, 20);
2364 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2365 break;
2366 default:
2367 return false;
2368 }
2369
Johnny Chen8fa20592011-02-18 01:22:22 +00002370 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002371 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002372 if (!success)
2373 return false;
2374
2375 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2376
2377 EmulateInstruction::Context context;
2378 context.type = EmulateInstruction::eContextImmediate;
2379 context.SetNoArgs ();
2380
2381 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2382 return false;
2383 }
2384 return true;
2385}
2386
Johnny Chend761dcf2011-02-17 22:03:29 +00002387// This instruction adds a register value and an optionally-shifted register value, and writes the result
2388// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002389bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002390EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002391{
2392#if 0
2393 // ARM pseudo code...
2394 if ConditionPassed() then
2395 EncodingSpecificOperations();
2396 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2397 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2398 if d == 15 then
2399 ALUWritePC(result); // setflags is always FALSE here
2400 else
2401 R[d] = result;
2402 if setflags then
2403 APSR.N = result<31>;
2404 APSR.Z = IsZeroBit(result);
2405 APSR.C = carry;
2406 APSR.V = overflow;
2407#endif
2408
2409 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002410
Greg Clayton7bc39082011-03-24 23:53:38 +00002411 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002412 {
2413 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002414 ARM_ShifterType shift_t;
2415 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002416 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002417 switch (encoding)
2418 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002419 case eEncodingT1:
2420 Rd = Bits32(opcode, 2, 0);
2421 Rn = Bits32(opcode, 5, 3);
2422 Rm = Bits32(opcode, 8, 6);
2423 setflags = !InITBlock();
2424 shift_t = SRType_LSL;
2425 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002426 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002427 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002428 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002429 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002430 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002431 shift_t = SRType_LSL;
2432 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002433 if (Rn == 15 && Rm == 15)
2434 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002435 if (Rd == 15 && InITBlock() && !LastInITBlock())
2436 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002437 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002438 case eEncodingA1:
2439 Rd = Bits32(opcode, 15, 12);
2440 Rn = Bits32(opcode, 19, 16);
2441 Rm = Bits32(opcode, 3, 0);
2442 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002443 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002444 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002445 default:
2446 return false;
2447 }
2448
Johnny Chen26863dc2011-02-09 23:43:29 +00002449 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002450 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002451 if (!success)
2452 return false;
2453
2454 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002455 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002456 if (!success)
2457 return false;
2458
Johnny Chene97c0d52011-02-18 19:32:20 +00002459 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002460 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002461
2462 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002463 context.type = EmulateInstruction::eContextAddition;
2464 Register op1_reg;
2465 Register op2_reg;
2466 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2467 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2468 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002469
Johnny Chen10530c22011-02-17 22:37:12 +00002470 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002471 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002472 }
2473 return true;
2474}
2475
Johnny Chen34075cb2011-02-22 01:56:31 +00002476// Compare Negative (immediate) adds a register value and an immediate value.
2477// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002478bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002479EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002480{
2481#if 0
2482 // ARM pseudo code...
2483 if ConditionPassed() then
2484 EncodingSpecificOperations();
2485 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2486 APSR.N = result<31>;
2487 APSR.Z = IsZeroBit(result);
2488 APSR.C = carry;
2489 APSR.V = overflow;
2490#endif
2491
2492 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002493
2494 uint32_t Rn; // the first operand
2495 uint32_t imm32; // the immediate value to be compared with
2496 switch (encoding) {
2497 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002498 Rn = Bits32(opcode, 19, 16);
2499 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2500 if (Rn == 15)
2501 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002502 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002503 case eEncodingA1:
2504 Rn = Bits32(opcode, 19, 16);
2505 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2506 break;
2507 default:
2508 return false;
2509 }
2510 // Read the register value from the operand register Rn.
2511 uint32_t reg_val = ReadCoreReg(Rn, &success);
2512 if (!success)
2513 return false;
2514
Johnny Chen078fbc62011-02-22 19:48:22 +00002515 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002516
2517 EmulateInstruction::Context context;
2518 context.type = EmulateInstruction::eContextImmediate;
2519 context.SetNoArgs ();
2520 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2521 return false;
2522
2523 return true;
2524}
2525
2526// Compare Negative (register) adds a register value and an optionally-shifted register value.
2527// It updates the condition flags based on the result, and discards the result.
2528bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002529EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002530{
2531#if 0
2532 // ARM pseudo code...
2533 if ConditionPassed() then
2534 EncodingSpecificOperations();
2535 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2536 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2537 APSR.N = result<31>;
2538 APSR.Z = IsZeroBit(result);
2539 APSR.C = carry;
2540 APSR.V = overflow;
2541#endif
2542
2543 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002544
2545 uint32_t Rn; // the first operand
2546 uint32_t Rm; // the second operand
2547 ARM_ShifterType shift_t;
2548 uint32_t shift_n; // the shift applied to the value read from Rm
2549 switch (encoding) {
2550 case eEncodingT1:
2551 Rn = Bits32(opcode, 2, 0);
2552 Rm = Bits32(opcode, 5, 3);
2553 shift_t = SRType_LSL;
2554 shift_n = 0;
2555 break;
2556 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002557 Rn = Bits32(opcode, 19, 16);
2558 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002559 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002560 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2561 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002562 return false;
2563 break;
2564 case eEncodingA1:
2565 Rn = Bits32(opcode, 19, 16);
2566 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002567 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002568 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002569 default:
2570 return false;
2571 }
2572 // Read the register value from register Rn.
2573 uint32_t val1 = ReadCoreReg(Rn, &success);
2574 if (!success)
2575 return false;
2576
2577 // Read the register value from register Rm.
2578 uint32_t val2 = ReadCoreReg(Rm, &success);
2579 if (!success)
2580 return false;
2581
2582 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002583 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002584
2585 EmulateInstruction::Context context;
2586 context.type = EmulateInstruction::eContextImmediate;
2587 context.SetNoArgs();
2588 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2589 return false;
2590
2591 return true;
2592}
2593
2594// Compare (immediate) subtracts an immediate value from a register value.
2595// It updates the condition flags based on the result, and discards the result.
2596bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002597EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002598{
2599#if 0
2600 // ARM pseudo code...
2601 if ConditionPassed() then
2602 EncodingSpecificOperations();
2603 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2604 APSR.N = result<31>;
2605 APSR.Z = IsZeroBit(result);
2606 APSR.C = carry;
2607 APSR.V = overflow;
2608#endif
2609
2610 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002611
2612 uint32_t Rn; // the first operand
2613 uint32_t imm32; // the immediate value to be compared with
2614 switch (encoding) {
2615 case eEncodingT1:
2616 Rn = Bits32(opcode, 10, 8);
2617 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002618 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002619 case eEncodingT2:
2620 Rn = Bits32(opcode, 19, 16);
2621 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2622 if (Rn == 15)
2623 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002624 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002625 case eEncodingA1:
2626 Rn = Bits32(opcode, 19, 16);
2627 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002628 break;
2629 default:
2630 return false;
2631 }
2632 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002633 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002634 if (!success)
2635 return false;
2636
Johnny Chen10530c22011-02-17 22:37:12 +00002637 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2638
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002639 EmulateInstruction::Context context;
2640 context.type = EmulateInstruction::eContextImmediate;
2641 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002642 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2643 return false;
2644
Johnny Chend4dc4442011-02-11 02:02:56 +00002645 return true;
2646}
2647
Johnny Chen34075cb2011-02-22 01:56:31 +00002648// Compare (register) subtracts an optionally-shifted register value from a register value.
2649// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002651EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002652{
2653#if 0
2654 // ARM pseudo code...
2655 if ConditionPassed() then
2656 EncodingSpecificOperations();
2657 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2658 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2659 APSR.N = result<31>;
2660 APSR.Z = IsZeroBit(result);
2661 APSR.C = carry;
2662 APSR.V = overflow;
2663#endif
2664
2665 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002666
2667 uint32_t Rn; // the first operand
2668 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002669 ARM_ShifterType shift_t;
2670 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002671 switch (encoding) {
2672 case eEncodingT1:
2673 Rn = Bits32(opcode, 2, 0);
2674 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002675 shift_t = SRType_LSL;
2676 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002677 break;
2678 case eEncodingT2:
2679 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2680 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002681 shift_t = SRType_LSL;
2682 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002683 if (Rn < 8 && Rm < 8)
2684 return false;
2685 if (Rn == 15 || Rm == 15)
2686 return false;
2687 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002688 case eEncodingA1:
2689 Rn = Bits32(opcode, 19, 16);
2690 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002691 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002692 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002693 default:
2694 return false;
2695 }
2696 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002697 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002698 if (!success)
2699 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002700
Johnny Chene4a4d302011-02-11 21:53:58 +00002701 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002702 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002703 if (!success)
2704 return false;
2705
Johnny Chen34075cb2011-02-22 01:56:31 +00002706 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2707 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002708
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002709 EmulateInstruction::Context context;
2710 context.type = EmulateInstruction::eContextImmediate;
2711 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002712 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2713 return false;
2714
Johnny Chene4a4d302011-02-11 21:53:58 +00002715 return true;
2716}
2717
Johnny Chen82f16aa2011-02-15 20:10:55 +00002718// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2719// shifting in copies of its sign bit, and writes the result to the destination register. It can
2720// optionally update the condition flags based on the result.
2721bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002722EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002723{
2724#if 0
2725 // ARM pseudo code...
2726 if ConditionPassed() then
2727 EncodingSpecificOperations();
2728 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2729 if d == 15 then // Can only occur for ARM encoding
2730 ALUWritePC(result); // setflags is always FALSE here
2731 else
2732 R[d] = result;
2733 if setflags then
2734 APSR.N = result<31>;
2735 APSR.Z = IsZeroBit(result);
2736 APSR.C = carry;
2737 // APSR.V unchanged
2738#endif
2739
Greg Clayton7bc39082011-03-24 23:53:38 +00002740 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002741}
2742
2743// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2744// shifting in copies of its sign bit, and writes the result to the destination register.
2745// The variable number of bits is read from the bottom byte of a register. It can optionally update
2746// the condition flags based on the result.
2747bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002748EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002749{
2750#if 0
2751 // ARM pseudo code...
2752 if ConditionPassed() then
2753 EncodingSpecificOperations();
2754 shift_n = UInt(R[m]<7:0>);
2755 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2756 R[d] = result;
2757 if setflags then
2758 APSR.N = result<31>;
2759 APSR.Z = IsZeroBit(result);
2760 APSR.C = carry;
2761 // APSR.V unchanged
2762#endif
2763
Greg Clayton7bc39082011-03-24 23:53:38 +00002764 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002765}
2766
2767// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2768// shifting in zeros, and writes the result to the destination register. It can optionally
2769// update the condition flags based on the result.
2770bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002771EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002772{
2773#if 0
2774 // ARM pseudo code...
2775 if ConditionPassed() then
2776 EncodingSpecificOperations();
2777 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2778 if d == 15 then // Can only occur for ARM encoding
2779 ALUWritePC(result); // setflags is always FALSE here
2780 else
2781 R[d] = result;
2782 if setflags then
2783 APSR.N = result<31>;
2784 APSR.Z = IsZeroBit(result);
2785 APSR.C = carry;
2786 // APSR.V unchanged
2787#endif
2788
Greg Clayton7bc39082011-03-24 23:53:38 +00002789 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002790}
2791
2792// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2793// shifting in zeros, and writes the result to the destination register. The variable number
2794// of bits is read from the bottom byte of a register. It can optionally update the condition
2795// flags based on the result.
2796bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002797EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002798{
2799#if 0
2800 // ARM pseudo code...
2801 if ConditionPassed() then
2802 EncodingSpecificOperations();
2803 shift_n = UInt(R[m]<7:0>);
2804 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2805 R[d] = result;
2806 if setflags then
2807 APSR.N = result<31>;
2808 APSR.Z = IsZeroBit(result);
2809 APSR.C = carry;
2810 // APSR.V unchanged
2811#endif
2812
Greg Clayton7bc39082011-03-24 23:53:38 +00002813 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002814}
2815
2816// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2817// shifting in zeros, and writes the result to the destination register. It can optionally
2818// update the condition flags based on the result.
2819bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002820EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002821{
2822#if 0
2823 // ARM pseudo code...
2824 if ConditionPassed() then
2825 EncodingSpecificOperations();
2826 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2827 if d == 15 then // Can only occur for ARM encoding
2828 ALUWritePC(result); // setflags is always FALSE here
2829 else
2830 R[d] = result;
2831 if setflags then
2832 APSR.N = result<31>;
2833 APSR.Z = IsZeroBit(result);
2834 APSR.C = carry;
2835 // APSR.V unchanged
2836#endif
2837
Greg Clayton7bc39082011-03-24 23:53:38 +00002838 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002839}
2840
2841// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2842// shifting in zeros, and writes the result to the destination register. The variable number
2843// of bits is read from the bottom byte of a register. It can optionally update the condition
2844// flags based on the result.
2845bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002846EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002847{
2848#if 0
2849 // ARM pseudo code...
2850 if ConditionPassed() then
2851 EncodingSpecificOperations();
2852 shift_n = UInt(R[m]<7:0>);
2853 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2854 R[d] = result;
2855 if setflags then
2856 APSR.N = result<31>;
2857 APSR.Z = IsZeroBit(result);
2858 APSR.C = carry;
2859 // APSR.V unchanged
2860#endif
2861
Greg Clayton7bc39082011-03-24 23:53:38 +00002862 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002863}
2864
Johnny Cheneeab4852011-02-16 22:14:44 +00002865// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2866// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2867// It can optionally update the condition flags based on the result.
2868bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002869EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002870{
2871#if 0
2872 // ARM pseudo code...
2873 if ConditionPassed() then
2874 EncodingSpecificOperations();
2875 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2876 if d == 15 then // Can only occur for ARM encoding
2877 ALUWritePC(result); // setflags is always FALSE here
2878 else
2879 R[d] = result;
2880 if setflags then
2881 APSR.N = result<31>;
2882 APSR.Z = IsZeroBit(result);
2883 APSR.C = carry;
2884 // APSR.V unchanged
2885#endif
2886
Greg Clayton7bc39082011-03-24 23:53:38 +00002887 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002888}
2889
2890// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2891// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2892// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2893// flags based on the result.
2894bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002895EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002896{
2897#if 0
2898 // ARM pseudo code...
2899 if ConditionPassed() then
2900 EncodingSpecificOperations();
2901 shift_n = UInt(R[m]<7:0>);
2902 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2903 R[d] = result;
2904 if setflags then
2905 APSR.N = result<31>;
2906 APSR.Z = IsZeroBit(result);
2907 APSR.C = carry;
2908 // APSR.V unchanged
2909#endif
2910
Greg Clayton7bc39082011-03-24 23:53:38 +00002911 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002912}
2913
2914// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2915// with the carry flag shifted into bit [31].
2916//
2917// RRX can optionally update the condition flags based on the result.
2918// In that case, bit [0] is shifted into the carry flag.
2919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002920EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002921{
2922#if 0
2923 // ARM pseudo code...
2924 if ConditionPassed() then
2925 EncodingSpecificOperations();
2926 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2927 if d == 15 then // Can only occur for ARM encoding
2928 ALUWritePC(result); // setflags is always FALSE here
2929 else
2930 R[d] = result;
2931 if setflags then
2932 APSR.N = result<31>;
2933 APSR.Z = IsZeroBit(result);
2934 APSR.C = carry;
2935 // APSR.V unchanged
2936#endif
2937
Greg Clayton7bc39082011-03-24 23:53:38 +00002938 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00002939}
2940
Johnny Chen41a0a152011-02-16 01:27:54 +00002941bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002942EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00002943{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002944 assert(shift_type == SRType_ASR
2945 || shift_type == SRType_LSL
2946 || shift_type == SRType_LSR
2947 || shift_type == SRType_ROR
2948 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00002949
Johnny Chen82f16aa2011-02-15 20:10:55 +00002950 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002951
Greg Clayton7bc39082011-03-24 23:53:38 +00002952 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002953 {
Johnny Chene7f89532011-02-15 23:22:46 +00002954 uint32_t Rd; // the destination register
2955 uint32_t Rm; // the first operand register
2956 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002957 uint32_t carry; // the carry bit after the shift operation
2958 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002959
2960 // Special case handling!
2961 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00002962 ARMEncoding use_encoding = encoding;
2963 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00002964 {
2965 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2966 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00002967 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00002968 }
2969
Greg Clayton7bc39082011-03-24 23:53:38 +00002970 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00002971 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002972 // Due to the above special case handling!
2973 assert(shift_type != SRType_ROR);
2974
Johnny Chen82f16aa2011-02-15 20:10:55 +00002975 Rd = Bits32(opcode, 2, 0);
2976 Rm = Bits32(opcode, 5, 3);
2977 setflags = !InITBlock();
2978 imm5 = Bits32(opcode, 10, 6);
2979 break;
2980 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002981 // A8.6.141 RRX
2982 assert(shift_type != SRType_RRX);
2983
Johnny Chen82f16aa2011-02-15 20:10:55 +00002984 Rd = Bits32(opcode, 11, 8);
2985 Rm = Bits32(opcode, 3, 0);
2986 setflags = BitIsSet(opcode, 20);
2987 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2988 if (BadReg(Rd) || BadReg(Rm))
2989 return false;
2990 break;
2991 case eEncodingA1:
2992 Rd = Bits32(opcode, 15, 12);
2993 Rm = Bits32(opcode, 3, 0);
2994 setflags = BitIsSet(opcode, 20);
2995 imm5 = Bits32(opcode, 11, 7);
2996 break;
2997 default:
2998 return false;
2999 }
3000
Johnny Cheneeab4852011-02-16 22:14:44 +00003001 // A8.6.139 ROR (immediate)
3002 if (shift_type == SRType_ROR && imm5 == 0)
3003 shift_type = SRType_RRX;
3004
Johnny Chen82f16aa2011-02-15 20:10:55 +00003005 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003006 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003007 if (!success)
3008 return false;
3009
Johnny Cheneeab4852011-02-16 22:14:44 +00003010 // Decode the shift amount if not RRX.
3011 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003012
Johnny Chene97c0d52011-02-18 19:32:20 +00003013 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003014
3015 // The context specifies that an immediate is to be moved into Rd.
3016 EmulateInstruction::Context context;
3017 context.type = EmulateInstruction::eContextImmediate;
3018 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003019
Johnny Chen10530c22011-02-17 22:37:12 +00003020 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003021 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003022 }
3023 return true;
3024}
3025
Johnny Chene7f89532011-02-15 23:22:46 +00003026bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003027EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003028{
Johnny Chen41a0a152011-02-16 01:27:54 +00003029 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003030
3031 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003032
Greg Clayton7bc39082011-03-24 23:53:38 +00003033 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003034 {
3035 uint32_t Rd; // the destination register
3036 uint32_t Rn; // the first operand register
3037 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3038 uint32_t carry; // the carry bit after the shift operation
3039 bool setflags;
3040 switch (encoding) {
3041 case eEncodingT1:
3042 Rd = Bits32(opcode, 2, 0);
3043 Rn = Rd;
3044 Rm = Bits32(opcode, 5, 3);
3045 setflags = !InITBlock();
3046 break;
3047 case eEncodingT2:
3048 Rd = Bits32(opcode, 11, 8);
3049 Rn = Bits32(opcode, 19, 16);
3050 Rm = Bits32(opcode, 3, 0);
3051 setflags = BitIsSet(opcode, 20);
3052 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3053 return false;
3054 break;
3055 case eEncodingA1:
3056 Rd = Bits32(opcode, 15, 12);
3057 Rn = Bits32(opcode, 3, 0);
3058 Rm = Bits32(opcode, 11, 8);
3059 setflags = BitIsSet(opcode, 20);
3060 if (Rd == 15 || Rn == 15 || Rm == 15)
3061 return false;
3062 break;
3063 default:
3064 return false;
3065 }
3066
3067 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003068 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003069 if (!success)
3070 return false;
3071 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003072 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003073 if (!success)
3074 return false;
3075
3076 // Get the shift amount.
3077 uint32_t amt = Bits32(val, 7, 0);
3078
Johnny Chene97c0d52011-02-18 19:32:20 +00003079 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003080
3081 // The context specifies that an immediate is to be moved into Rd.
3082 EmulateInstruction::Context context;
3083 context.type = EmulateInstruction::eContextImmediate;
3084 context.SetNoArgs ();
3085
Johnny Chen10530c22011-02-17 22:37:12 +00003086 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003087 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003088 }
3089 return true;
3090}
3091
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003092// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003093// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003094// can be written back to the base register.
3095bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003096EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003097{
3098#if 0
3099 // ARM pseudo code...
3100 if ConditionPassed()
3101 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3102 address = R[n];
3103
3104 for i = 0 to 14
3105 if registers<i> == '1' then
3106 R[i] = MemA[address, 4]; address = address + 4;
3107 if registers<15> == '1' then
3108 LoadWritePC (MemA[address, 4]);
3109
3110 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3111 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3112
3113#endif
3114
3115 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003116
Greg Clayton7bc39082011-03-24 23:53:38 +00003117 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003118 {
3119 uint32_t n;
3120 uint32_t registers = 0;
3121 bool wback;
3122 const uint32_t addr_byte_size = GetAddressByteSize();
3123 switch (encoding)
3124 {
3125 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003126 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003127 n = Bits32 (opcode, 10, 8);
3128 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003129 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003130 wback = BitIsClear (registers, n);
3131 // if BitCount(registers) < 1 then UNPREDICTABLE;
3132 if (BitCount(registers) < 1)
3133 return false;
3134 break;
3135 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003136 // if W == '1' && Rn == '1101' then SEE POP;
3137 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003138 n = Bits32 (opcode, 19, 16);
3139 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003140 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003141 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003142
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003143 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003144 if ((n == 15)
3145 || (BitCount (registers) < 2)
3146 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3147 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003148
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003149 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003150 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003151 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003152
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003153 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003154 if (wback
3155 && BitIsSet (registers, n))
3156 return false;
3157 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003158
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003159 case eEncodingA1:
3160 n = Bits32 (opcode, 19, 16);
3161 registers = Bits32 (opcode, 15, 0);
3162 wback = BitIsSet (opcode, 21);
3163 if ((n == 15)
3164 || (BitCount (registers) < 1))
3165 return false;
3166 break;
3167 default:
3168 return false;
3169 }
3170
3171 int32_t offset = 0;
3172 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3173 if (!success)
3174 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003175
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003176 EmulateInstruction::Context context;
3177 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3178 Register dwarf_reg;
3179 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3180 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003181
3182 for (int i = 0; i < 14; ++i)
3183 {
3184 if (BitIsSet (registers, i))
3185 {
Caroline Tice85aab332011-02-08 23:56:10 +00003186 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003187 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003188 if (wback && (n == 13)) // Pop Instruction
3189 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3190
3191 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003192 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003193 if (!success)
3194 return false;
3195
3196 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3197 return false;
3198
3199 offset += addr_byte_size;
3200 }
3201 }
3202
3203 if (BitIsSet (registers, 15))
3204 {
3205 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003206 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003207 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003208 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003209 if (!success)
3210 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003211 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003212 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003213 return false;
3214 }
3215
3216 if (wback && BitIsClear (registers, n))
3217 {
Caroline Ticefa172202011-02-11 22:49:54 +00003218 // R[n] = R[n] + 4 * BitCount (registers)
3219 int32_t offset = addr_byte_size * BitCount (registers);
3220 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003221 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003222
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003223 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3224 return false;
3225 }
3226 if (wback && BitIsSet (registers, n))
3227 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003228 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003229 }
3230 return true;
3231}
Caroline Tice713c2662011-02-11 17:59:55 +00003232
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003233// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3234// The consecutive memory locations end at this address and the address just below the lowest of those locations
3235// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003236bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003237EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003238{
3239#if 0
3240 // ARM pseudo code...
3241 if ConditionPassed() then
3242 EncodingSpecificOperations();
3243 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244
Caroline Tice713c2662011-02-11 17:59:55 +00003245 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003246 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003247 R[i] = MemA[address,4]; address = address + 4;
3248
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003249 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003250 LoadWritePC(MemA[address,4]);
3251
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003252 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3253 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003254#endif
3255
3256 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003257
Greg Clayton7bc39082011-03-24 23:53:38 +00003258 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003259 {
3260 uint32_t n;
3261 uint32_t registers = 0;
3262 bool wback;
3263 const uint32_t addr_byte_size = GetAddressByteSize();
3264
3265 // EncodingSpecificOperations();
3266 switch (encoding)
3267 {
3268 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003269 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003270 n = Bits32 (opcode, 19, 16);
3271 registers = Bits32 (opcode, 15, 0);
3272 wback = BitIsSet (opcode, 21);
3273
3274 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3275 if ((n == 15) || (BitCount (registers) < 1))
3276 return false;
3277
3278 break;
3279
3280 default:
3281 return false;
3282 }
3283 // address = R[n] - 4*BitCount(registers) + 4;
3284
3285 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003286 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003287
3288 if (!success)
3289 return false;
3290
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003291 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003292
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003293 EmulateInstruction::Context context;
3294 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3295 Register dwarf_reg;
3296 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3297 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003298
3299 // for i = 0 to 14
3300 for (int i = 0; i < 14; ++i)
3301 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003302 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003303 if (BitIsSet (registers, i))
3304 {
3305 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003306 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003307 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003308 if (!success)
3309 return false;
3310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3311 return false;
3312 offset += addr_byte_size;
3313 }
3314 }
3315
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003316 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003317 // LoadWritePC(MemA[address,4]);
3318 if (BitIsSet (registers, 15))
3319 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003320 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003321 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003322 if (!success)
3323 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003324 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003325 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003326 return false;
3327 }
3328
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003329 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003330 if (wback && BitIsClear (registers, n))
3331 {
Caroline Tice713c2662011-02-11 17:59:55 +00003332 if (!success)
3333 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003334
3335 offset = (addr_byte_size * BitCount (registers)) * -1;
3336 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003337 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003338 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003339 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3340 return false;
3341 }
3342
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003343 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003344 if (wback && BitIsSet (registers, n))
3345 return WriteBits32Unknown (n);
3346 }
3347 return true;
3348}
3349
3350// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3351// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3352// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003353bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003354EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003355{
3356#if 0
3357 // ARM pseudo code...
3358 if ConditionPassed() then
3359 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3360 address = R[n] - 4*BitCount(registers);
3361
3362 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003363 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003364 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003365 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003366 LoadWritePC(MemA[address,4]);
3367
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003368 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3369 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003370#endif
3371
3372 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003373
Greg Clayton7bc39082011-03-24 23:53:38 +00003374 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003375 {
3376 uint32_t n;
3377 uint32_t registers = 0;
3378 bool wback;
3379 const uint32_t addr_byte_size = GetAddressByteSize();
3380 switch (encoding)
3381 {
3382 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003383 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003384 n = Bits32 (opcode, 19, 16);
3385 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003386 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003387 wback = BitIsSet (opcode, 21);
3388
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003389 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003390 if ((n == 15)
3391 || (BitCount (registers) < 2)
3392 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3393 return false;
3394
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003395 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003396 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003397 return false;
3398
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003399 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003400 if (wback && BitIsSet (registers, n))
3401 return false;
3402
3403 break;
3404
3405 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003406 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003407 n = Bits32 (opcode, 19, 16);
3408 registers = Bits32 (opcode, 15, 0);
3409 wback = BitIsSet (opcode, 21);
3410
3411 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3412 if ((n == 15) || (BitCount (registers) < 1))
3413 return false;
3414
3415 break;
3416
3417 default:
3418 return false;
3419 }
3420
Caroline Tice713c2662011-02-11 17:59:55 +00003421 // address = R[n] - 4*BitCount(registers);
3422
Caroline Tice0b29e242011-02-08 23:16:02 +00003423 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003424 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003425
3426 if (!success)
3427 return false;
3428
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003429 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003430 EmulateInstruction::Context context;
3431 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3432 Register dwarf_reg;
3433 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003434 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003435
3436 for (int i = 0; i < 14; ++i)
3437 {
3438 if (BitIsSet (registers, i))
3439 {
3440 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003441 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003442 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003443 if (!success)
3444 return false;
3445
3446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3447 return false;
3448
3449 offset += addr_byte_size;
3450 }
3451 }
3452
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003453 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003454 // LoadWritePC(MemA[address,4]);
3455 if (BitIsSet (registers, 15))
3456 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003457 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003458 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003459 if (!success)
3460 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003461 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003462 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003463 return false;
3464 }
3465
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003466 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003467 if (wback && BitIsClear (registers, n))
3468 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003469 if (!success)
3470 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003471
3472 offset = (addr_byte_size * BitCount (registers)) * -1;
3473 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003474 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003475 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003476 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3477 return false;
3478 }
3479
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003480 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003481 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003482 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003483 }
3484 return true;
3485}
Caroline Tice85aab332011-02-08 23:56:10 +00003486
Caroline Tice713c2662011-02-11 17:59:55 +00003487// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3488// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3489// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003490bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003491EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003492{
3493#if 0
3494 if ConditionPassed() then
3495 EncodingSpecificOperations();
3496 address = R[n] + 4;
3497
3498 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003499 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003500 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003501 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003502 LoadWritePC(MemA[address,4]);
3503
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003504 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3505 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003506#endif
3507
3508 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003509
Greg Clayton7bc39082011-03-24 23:53:38 +00003510 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003511 {
3512 uint32_t n;
3513 uint32_t registers = 0;
3514 bool wback;
3515 const uint32_t addr_byte_size = GetAddressByteSize();
3516 switch (encoding)
3517 {
3518 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003519 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003520 n = Bits32 (opcode, 19, 16);
3521 registers = Bits32 (opcode, 15, 0);
3522 wback = BitIsSet (opcode, 21);
3523
3524 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3525 if ((n == 15) || (BitCount (registers) < 1))
3526 return false;
3527
3528 break;
3529 default:
3530 return false;
3531 }
3532 // address = R[n] + 4;
3533
3534 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003535 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003536
3537 if (!success)
3538 return false;
3539
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003540 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003541
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003542 EmulateInstruction::Context context;
3543 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3544 Register dwarf_reg;
3545 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3546 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003547
3548 for (int i = 0; i < 14; ++i)
3549 {
3550 if (BitIsSet (registers, i))
3551 {
3552 // R[i] = MemA[address,4]; address = address + 4;
3553
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003554 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003555 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003556 if (!success)
3557 return false;
3558
3559 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3560 return false;
3561
3562 offset += addr_byte_size;
3563 }
3564 }
3565
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003566 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003567 // LoadWritePC(MemA[address,4]);
3568 if (BitIsSet (registers, 15))
3569 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003570 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003571 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003572 if (!success)
3573 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003574 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003575 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003576 return false;
3577 }
3578
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003579 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003580 if (wback && BitIsClear (registers, n))
3581 {
Caroline Tice85aab332011-02-08 23:56:10 +00003582 if (!success)
3583 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003584
3585 offset = addr_byte_size * BitCount (registers);
3586 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003587 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003588 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003589 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3590 return false;
3591 }
3592
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003593 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003594 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003595 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003596 }
3597 return true;
3598}
Caroline Tice0b29e242011-02-08 23:16:02 +00003599
Johnny Chenef21b592011-02-10 01:52:38 +00003600// Load Register (immediate) calculates an address from a base register value and
3601// an immediate offset, loads a word from memory, and writes to a register.
3602// LDR (immediate, Thumb)
3603bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003604EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003605{
3606#if 0
3607 // ARM pseudo code...
3608 if (ConditionPassed())
3609 {
3610 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3611 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3612 address = if index then offset_addr else R[n];
3613 data = MemU[address,4];
3614 if wback then R[n] = offset_addr;
3615 if t == 15 then
3616 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3617 elsif UnalignedSupport() || address<1:0> = '00' then
3618 R[t] = data;
3619 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3620 }
3621#endif
3622
3623 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003624
Greg Clayton7bc39082011-03-24 23:53:38 +00003625 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003626 {
3627 uint32_t Rt; // the destination register
3628 uint32_t Rn; // the base register
3629 uint32_t imm32; // the immediate offset used to form the address
3630 addr_t offset_addr; // the offset address
3631 addr_t address; // the calculated address
3632 uint32_t data; // the literal data value from memory load
3633 bool add, index, wback;
3634 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003635 case eEncodingT1:
3636 Rt = Bits32(opcode, 5, 3);
3637 Rn = Bits32(opcode, 2, 0);
3638 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3639 // index = TRUE; add = TRUE; wback = FALSE
3640 add = true;
3641 index = true;
3642 wback = false;
3643
3644 break;
3645
3646 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003647 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003648 Rt = Bits32 (opcode, 10, 8);
3649 Rn = 13;
3650 imm32 = Bits32 (opcode, 7, 0) << 2;
3651
3652 // index = TRUE; add = TRUE; wback = FALSE;
3653 index = true;
3654 add = true;
3655 wback = false;
3656
3657 break;
3658
3659 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003660 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003661 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3662 Rt = Bits32 (opcode, 15, 12);
3663 Rn = Bits32 (opcode, 19, 16);
3664 imm32 = Bits32 (opcode, 11, 0);
3665
3666 // index = TRUE; add = TRUE; wback = FALSE;
3667 index = true;
3668 add = true;
3669 wback = false;
3670
3671 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3672 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3673 return false;
3674
3675 break;
3676
3677 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003678 // if Rn == '1111' then SEE LDR (literal);
3679 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3680 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3681 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003682 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3683 return false;
3684
3685 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3686 Rt = Bits32 (opcode, 15, 12);
3687 Rn = Bits32 (opcode, 19, 16);
3688 imm32 = Bits32 (opcode, 7, 0);
3689
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003690 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003691 index = BitIsSet (opcode, 10);
3692 add = BitIsSet (opcode, 9);
3693 wback = BitIsSet (opcode, 8);
3694
3695 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3696 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3697 return false;
3698
3699 break;
3700
3701 default:
3702 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003703 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003704 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003705 if (!success)
3706 return false;
3707 if (add)
3708 offset_addr = base + imm32;
3709 else
3710 offset_addr = base - imm32;
3711
3712 address = (index ? offset_addr : base);
3713
Caroline Ticebaf1f642011-03-24 19:23:45 +00003714 Register base_reg;
3715 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003716 if (wback)
3717 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003718 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003719 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3720 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003721
Johnny Chenef21b592011-02-10 01:52:38 +00003722 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3723 return false;
3724 }
3725
3726 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003727 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003728 context.type = EmulateInstruction::eContextRegisterLoad;
3729 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003730
3731 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003732 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003733 if (!success)
3734 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003735
3736 if (Rt == 15)
3737 {
3738 if (Bits32(address, 1, 0) == 0)
3739 {
Johnny Chen668b4512011-02-15 21:08:58 +00003740 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003741 return false;
3742 }
3743 else
3744 return false;
3745 }
3746 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3747 {
3748 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3749 return false;
3750 }
3751 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003752 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003753 }
3754 return true;
3755}
3756
Caroline Ticeaf556562011-02-15 18:42:15 +00003757// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3758// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3759// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003760bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003761EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003762{
3763#if 0
3764 if ConditionPassed() then
3765 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3766 address = R[n];
3767
3768 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003769 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003770 if i == n && wback && i != LowestSetBit(registers) then
3771 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3772 else
3773 MemA[address,4] = R[i];
3774 address = address + 4;
3775
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003776 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003777 MemA[address,4] = PCStoreValue();
3778 if wback then R[n] = R[n] + 4*BitCount(registers);
3779#endif
3780
3781 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003782
Greg Clayton7bc39082011-03-24 23:53:38 +00003783 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003784 {
3785 uint32_t n;
3786 uint32_t registers = 0;
3787 bool wback;
3788 const uint32_t addr_byte_size = GetAddressByteSize();
3789
3790 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3791 switch (encoding)
3792 {
3793 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003794 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003795 n = Bits32 (opcode, 10, 8);
3796 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003797 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003798 wback = true;
3799
3800 // if BitCount(registers) < 1 then UNPREDICTABLE;
3801 if (BitCount (registers) < 1)
3802 return false;
3803
3804 break;
3805
3806 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003807 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003808 n = Bits32 (opcode, 19, 16);
3809 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003810 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003811 wback = BitIsSet (opcode, 21);
3812
3813 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3814 if ((n == 15) || (BitCount (registers) < 2))
3815 return false;
3816
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003817 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003818 if (wback && BitIsSet (registers, n))
3819 return false;
3820
3821 break;
3822
3823 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003824 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003825 n = Bits32 (opcode, 19, 16);
3826 registers = Bits32 (opcode, 15, 0);
3827 wback = BitIsSet (opcode, 21);
3828
3829 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3830 if ((n == 15) || (BitCount (registers) < 1))
3831 return false;
3832
3833 break;
3834
3835 default:
3836 return false;
3837 }
3838
3839 // address = R[n];
3840 int32_t offset = 0;
3841 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3842 if (!success)
3843 return false;
3844
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003845 EmulateInstruction::Context context;
3846 context.type = EmulateInstruction::eContextRegisterStore;
3847 Register base_reg;
3848 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003849
3850 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003851 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003852 for (int i = 0; i < 14; ++i)
3853 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003854 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003855 if (BitIsSet (registers, i))
3856 {
3857 if (i < lowest_set_bit)
3858 lowest_set_bit = i;
3859 // if i == n && wback && i != LowestSetBit(registers) then
3860 if ((i == n) && wback && (i != lowest_set_bit))
3861 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3862 WriteBits32UnknownToMemory (address + offset);
3863 else
3864 {
3865 // MemA[address,4] = R[i];
3866 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3867 if (!success)
3868 return false;
3869
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003870 Register data_reg;
3871 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3872 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003873 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003874 return false;
3875 }
3876
3877 // address = address + 4;
3878 offset += addr_byte_size;
3879 }
3880 }
3881
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003882 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003883 // MemA[address,4] = PCStoreValue();
3884 if (BitIsSet (registers, 15))
3885 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003886 Register pc_reg;
3887 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3888 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003889 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003890 if (!success)
3891 return false;
3892
Caroline Tice8d681f52011-03-17 23:50:16 +00003893 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003894 return false;
3895 }
3896
3897 // if wback then R[n] = R[n] + 4*BitCount(registers);
3898 if (wback)
3899 {
3900 offset = addr_byte_size * BitCount (registers);
3901 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003902 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003903 addr_t data = address + offset;
3904 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3905 return false;
3906 }
3907 }
3908 return true;
3909}
3910
Caroline Ticeaf556562011-02-15 18:42:15 +00003911// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3912// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3913// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003914bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003915EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00003916{
3917#if 0
3918 if ConditionPassed() then
3919 EncodingSpecificOperations();
3920 address = R[n] - 4*BitCount(registers) + 4;
3921
3922 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003923 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003924 if i == n && wback && i != LowestSetBit(registers) then
3925 MemA[address,4] = bits(32) UNKNOWN;
3926 else
3927 MemA[address,4] = R[i];
3928 address = address + 4;
3929
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003930 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003931 MemA[address,4] = PCStoreValue();
3932
3933 if wback then R[n] = R[n] - 4*BitCount(registers);
3934#endif
3935
3936 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00003937
Greg Clayton7bc39082011-03-24 23:53:38 +00003938 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00003939 {
3940 uint32_t n;
3941 uint32_t registers = 0;
3942 bool wback;
3943 const uint32_t addr_byte_size = GetAddressByteSize();
3944
3945 // EncodingSpecificOperations();
3946 switch (encoding)
3947 {
3948 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003949 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00003950 n = Bits32 (opcode, 19, 16);
3951 registers = Bits32 (opcode, 15, 0);
3952 wback = BitIsSet (opcode, 21);
3953
3954 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3955 if ((n == 15) || (BitCount (registers) < 1))
3956 return false;
3957 break;
3958 default:
3959 return false;
3960 }
3961
3962 // address = R[n] - 4*BitCount(registers) + 4;
3963 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003964 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00003965 if (!success)
3966 return false;
3967
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003968 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00003969
3970 EmulateInstruction::Context context;
3971 context.type = EmulateInstruction::eContextRegisterStore;
3972 Register base_reg;
3973 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3974
3975 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003976 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00003977 for (int i = 0; i < 14; ++i)
3978 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003979 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003980 if (BitIsSet (registers, i))
3981 {
3982 if (i < lowest_bit_set)
3983 lowest_bit_set = i;
3984 //if i == n && wback && i != LowestSetBit(registers) then
3985 if ((i == n) && wback && (i != lowest_bit_set))
3986 // MemA[address,4] = bits(32) UNKNOWN;
3987 WriteBits32UnknownToMemory (address + offset);
3988 else
3989 {
3990 // MemA[address,4] = R[i];
3991 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3992 if (!success)
3993 return false;
3994
3995 Register data_reg;
3996 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003997 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003998 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003999 return false;
4000 }
4001
4002 // address = address + 4;
4003 offset += addr_byte_size;
4004 }
4005 }
4006
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004007 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004008 // MemA[address,4] = PCStoreValue();
4009 if (BitIsSet (registers, 15))
4010 {
4011 Register pc_reg;
4012 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4013 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004014 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004015 if (!success)
4016 return false;
4017
Caroline Tice8d681f52011-03-17 23:50:16 +00004018 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004019 return false;
4020 }
4021
4022 // if wback then R[n] = R[n] - 4*BitCount(registers);
4023 if (wback)
4024 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004025 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004026 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4027 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004028 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004029 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4030 return false;
4031 }
4032 }
4033 return true;
4034}
4035
Caroline Ticeaf556562011-02-15 18:42:15 +00004036// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4037// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4038// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004039bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004040EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004041{
4042#if 0
4043 if ConditionPassed() then
4044 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4045 address = R[n] - 4*BitCount(registers);
4046
4047 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004048 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004049 if i == n && wback && i != LowestSetBit(registers) then
4050 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4051 else
4052 MemA[address,4] = R[i];
4053 address = address + 4;
4054
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004055 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004056 MemA[address,4] = PCStoreValue();
4057
4058 if wback then R[n] = R[n] - 4*BitCount(registers);
4059#endif
4060
4061
4062 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004063
Greg Clayton7bc39082011-03-24 23:53:38 +00004064 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004065 {
4066 uint32_t n;
4067 uint32_t registers = 0;
4068 bool wback;
4069 const uint32_t addr_byte_size = GetAddressByteSize();
4070
4071 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4072 switch (encoding)
4073 {
4074 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004075 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004076 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4077 {
4078 // See PUSH
4079 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004080 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004081 n = Bits32 (opcode, 19, 16);
4082 registers = Bits32 (opcode, 15, 0);
4083 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4084 wback = BitIsSet (opcode, 21);
4085 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4086 if ((n == 15) || BitCount (registers) < 2)
4087 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004088 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004089 if (wback && BitIsSet (registers, n))
4090 return false;
4091 break;
4092
4093 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004094 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004095 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4096 {
4097 // See Push
4098 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004099 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004100 n = Bits32 (opcode, 19, 16);
4101 registers = Bits32 (opcode, 15, 0);
4102 wback = BitIsSet (opcode, 21);
4103 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4104 if ((n == 15) || BitCount (registers) < 1)
4105 return false;
4106 break;
4107
4108 default:
4109 return false;
4110 }
4111
4112 // address = R[n] - 4*BitCount(registers);
4113
4114 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004115 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004116 if (!success)
4117 return false;
4118
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004119 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004120
4121 EmulateInstruction::Context context;
4122 context.type = EmulateInstruction::eContextRegisterStore;
4123 Register base_reg;
4124 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4125
4126 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004127 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004128 for (int i = 0; i < 14; ++i)
4129 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004130 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004131 if (BitIsSet (registers, i))
4132 {
4133 if (i < lowest_set_bit)
4134 lowest_set_bit = i;
4135 // if i == n && wback && i != LowestSetBit(registers) then
4136 if ((i == n) && wback && (i != lowest_set_bit))
4137 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4138 WriteBits32UnknownToMemory (address + offset);
4139 else
4140 {
4141 // MemA[address,4] = R[i];
4142 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4143 if (!success)
4144 return false;
4145
4146 Register data_reg;
4147 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004148 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004149 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004150 return false;
4151 }
4152
4153 // address = address + 4;
4154 offset += addr_byte_size;
4155 }
4156 }
4157
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004158 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004159 // MemA[address,4] = PCStoreValue();
4160 if (BitIsSet (registers, 15))
4161 {
4162 Register pc_reg;
4163 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4164 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004165 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004166 if (!success)
4167 return false;
4168
Caroline Tice8d681f52011-03-17 23:50:16 +00004169 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004170 return false;
4171 }
4172
4173 // if wback then R[n] = R[n] - 4*BitCount(registers);
4174 if (wback)
4175 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004176 offset = (addr_byte_size * BitCount (registers)) * -1;
4177 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4178 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004179 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004180 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4181 return false;
4182 }
4183 }
4184 return true;
4185}
4186
4187// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4188// from a base register. The consecutive memory locations start just above this address, and the address of the last
4189// of those locations can optionally be written back to the base register.
4190bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004191EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004192{
4193#if 0
4194 if ConditionPassed() then
4195 EncodingSpecificOperations();
4196 address = R[n] + 4;
4197
4198 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004199 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004200 if i == n && wback && i != LowestSetBit(registers) then
4201 MemA[address,4] = bits(32) UNKNOWN;
4202 else
4203 MemA[address,4] = R[i];
4204 address = address + 4;
4205
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004206 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004207 MemA[address,4] = PCStoreValue();
4208
4209 if wback then R[n] = R[n] + 4*BitCount(registers);
4210#endif
4211
4212 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004213
Greg Clayton7bc39082011-03-24 23:53:38 +00004214 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004215 {
4216 uint32_t n;
4217 uint32_t registers = 0;
4218 bool wback;
4219 const uint32_t addr_byte_size = GetAddressByteSize();
4220
4221 // EncodingSpecificOperations();
4222 switch (encoding)
4223 {
4224 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004225 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004226 n = Bits32 (opcode, 19, 16);
4227 registers = Bits32 (opcode, 15, 0);
4228 wback = BitIsSet (opcode, 21);
4229
4230 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4231 if ((n == 15) && (BitCount (registers) < 1))
4232 return false;
4233 break;
4234 default:
4235 return false;
4236 }
4237 // address = R[n] + 4;
4238
4239 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004240 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004241 if (!success)
4242 return false;
4243
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004244 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004245
4246 EmulateInstruction::Context context;
4247 context.type = EmulateInstruction::eContextRegisterStore;
4248 Register base_reg;
4249 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4250
4251 uint32_t lowest_set_bit = 14;
4252 // for i = 0 to 14
4253 for (int i = 0; i < 14; ++i)
4254 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004255 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004256 if (BitIsSet (registers, i))
4257 {
4258 if (i < lowest_set_bit)
4259 lowest_set_bit = i;
4260 // if i == n && wback && i != LowestSetBit(registers) then
4261 if ((i == n) && wback && (i != lowest_set_bit))
4262 // MemA[address,4] = bits(32) UNKNOWN;
4263 WriteBits32UnknownToMemory (address + offset);
4264 // else
4265 else
4266 {
4267 // MemA[address,4] = R[i];
4268 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4269 if (!success)
4270 return false;
4271
4272 Register data_reg;
4273 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004274 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004275 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004276 return false;
4277 }
4278
4279 // address = address + 4;
4280 offset += addr_byte_size;
4281 }
4282 }
4283
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004284 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004285 // MemA[address,4] = PCStoreValue();
4286 if (BitIsSet (registers, 15))
4287 {
4288 Register pc_reg;
4289 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4290 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004291 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004292 if (!success)
4293 return false;
4294
Caroline Tice8d681f52011-03-17 23:50:16 +00004295 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004296 return false;
4297 }
4298
4299 // if wback then R[n] = R[n] + 4*BitCount(registers);
4300 if (wback)
4301 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004302 offset = addr_byte_size * BitCount (registers);
4303 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4304 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004305 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004306 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4307 return false;
4308 }
4309 }
4310 return true;
4311}
Caroline Tice7fac8572011-02-15 22:53:54 +00004312
4313// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4314// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004316EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004317{
4318#if 0
4319 if ConditionPassed() then
4320 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4321 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4322 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004323 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004324 MemU[address,4] = R[t];
4325 else // Can only occur before ARMv7
4326 MemU[address,4] = bits(32) UNKNOWN;
4327 if wback then R[n] = offset_addr;
4328#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004329
Caroline Tice7fac8572011-02-15 22:53:54 +00004330 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004331
Greg Clayton7bc39082011-03-24 23:53:38 +00004332 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004333 {
4334 const uint32_t addr_byte_size = GetAddressByteSize();
4335
4336 uint32_t t;
4337 uint32_t n;
4338 uint32_t imm32;
4339 bool index;
4340 bool add;
4341 bool wback;
4342 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4343 switch (encoding)
4344 {
4345 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004346 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004347 t = Bits32 (opcode, 2, 0);
4348 n = Bits32 (opcode, 5, 3);
4349 imm32 = Bits32 (opcode, 10, 6) << 2;
4350
4351 // index = TRUE; add = TRUE; wback = FALSE;
4352 index = true;
4353 add = false;
4354 wback = false;
4355 break;
4356
4357 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004358 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004359 t = Bits32 (opcode, 10, 8);
4360 n = 13;
4361 imm32 = Bits32 (opcode, 7, 0) << 2;
4362
4363 // index = TRUE; add = TRUE; wback = FALSE;
4364 index = true;
4365 add = true;
4366 wback = false;
4367 break;
4368
4369 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004370 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004371 if (Bits32 (opcode, 19, 16) == 15)
4372 return false;
4373
4374 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4375 t = Bits32 (opcode, 15, 12);
4376 n = Bits32 (opcode, 19, 16);
4377 imm32 = Bits32 (opcode, 11, 0);
4378
4379 // index = TRUE; add = TRUE; wback = FALSE;
4380 index = true;
4381 add = true;
4382 wback = false;
4383
4384 // if t == 15 then UNPREDICTABLE;
4385 if (t == 15)
4386 return false;
4387 break;
4388
4389 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004390 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4391 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4392 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004393 if ((Bits32 (opcode, 19, 16) == 15)
4394 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4395 return false;
4396
4397 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4398 t = Bits32 (opcode, 15, 12);
4399 n = Bits32 (opcode, 19, 16);
4400 imm32 = Bits32 (opcode, 7, 0);
4401
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004402 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004403 index = BitIsSet (opcode, 10);
4404 add = BitIsSet (opcode, 9);
4405 wback = BitIsSet (opcode, 8);
4406
4407 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4408 if ((t == 15) || (wback && (n == t)))
4409 return false;
4410 break;
4411
4412 default:
4413 return false;
4414 }
4415
4416 addr_t offset_addr;
4417 addr_t address;
4418
4419 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004420 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004421 if (!success)
4422 return false;
4423
4424 if (add)
4425 offset_addr = base_address + imm32;
4426 else
4427 offset_addr = base_address - imm32;
4428
4429 // address = if index then offset_addr else R[n];
4430 if (index)
4431 address = offset_addr;
4432 else
4433 address = base_address;
4434
4435 EmulateInstruction::Context context;
4436 context.type = eContextRegisterStore;
4437 Register base_reg;
4438 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4439
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004440 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004441 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4442 {
4443 // MemU[address,4] = R[t];
4444 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4445 if (!success)
4446 return false;
4447
4448 Register data_reg;
4449 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4450 int32_t offset = address - base_address;
4451 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004452 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004453 return false;
4454 }
4455 else
4456 {
4457 // MemU[address,4] = bits(32) UNKNOWN;
4458 WriteBits32UnknownToMemory (address);
4459 }
4460
4461 // if wback then R[n] = offset_addr;
4462 if (wback)
4463 {
4464 context.type = eContextRegisterLoad;
4465 context.SetAddress (offset_addr);
4466 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4467 return false;
4468 }
4469 }
4470 return true;
4471}
Caroline Ticeaf556562011-02-15 18:42:15 +00004472
Caroline Tice3fd63e92011-02-16 00:33:43 +00004473// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4474// word from a register to memory. The offset register value can optionally be shifted.
4475bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004476EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004477{
4478#if 0
4479 if ConditionPassed() then
4480 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4481 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4482 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4483 address = if index then offset_addr else R[n];
4484 if t == 15 then // Only possible for encoding A1
4485 data = PCStoreValue();
4486 else
4487 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004488 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004489 MemU[address,4] = data;
4490 else // Can only occur before ARMv7
4491 MemU[address,4] = bits(32) UNKNOWN;
4492 if wback then R[n] = offset_addr;
4493#endif
4494
4495 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004496
Greg Clayton7bc39082011-03-24 23:53:38 +00004497 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004498 {
4499 const uint32_t addr_byte_size = GetAddressByteSize();
4500
4501 uint32_t t;
4502 uint32_t n;
4503 uint32_t m;
4504 ARM_ShifterType shift_t;
4505 uint32_t shift_n;
4506 bool index;
4507 bool add;
4508 bool wback;
4509
4510 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4511 switch (encoding)
4512 {
4513 case eEncodingT1:
4514 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4515 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4516 t = Bits32 (opcode, 2, 0);
4517 n = Bits32 (opcode, 5, 3);
4518 m = Bits32 (opcode, 8, 6);
4519
4520 // index = TRUE; add = TRUE; wback = FALSE;
4521 index = true;
4522 add = true;
4523 wback = false;
4524
4525 // (shift_t, shift_n) = (SRType_LSL, 0);
4526 shift_t = SRType_LSL;
4527 shift_n = 0;
4528 break;
4529
4530 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004531 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004532 if (Bits32 (opcode, 19, 16) == 15)
4533 return false;
4534
4535 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4536 t = Bits32 (opcode, 15, 12);
4537 n = Bits32 (opcode, 19, 16);
4538 m = Bits32 (opcode, 3, 0);
4539
4540 // index = TRUE; add = TRUE; wback = FALSE;
4541 index = true;
4542 add = true;
4543 wback = false;
4544
4545 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4546 shift_t = SRType_LSL;
4547 shift_n = Bits32 (opcode, 5, 4);
4548
4549 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4550 if ((t == 15) || (BadReg (m)))
4551 return false;
4552 break;
4553
4554 case eEncodingA1:
4555 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004556 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004557 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4558 t = Bits32 (opcode, 15, 12);
4559 n = Bits32 (opcode, 19, 16);
4560 m = Bits32 (opcode, 3, 0);
4561
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004562 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004563 index = BitIsSet (opcode, 24);
4564 add = BitIsSet (opcode, 23);
4565 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4566
4567 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4568 uint32_t typ = Bits32 (opcode, 6, 5);
4569 uint32_t imm5 = Bits32 (opcode, 11, 7);
4570 shift_n = DecodeImmShift(typ, imm5, shift_t);
4571
4572 // if m == 15 then UNPREDICTABLE;
4573 if (m == 15)
4574 return false;
4575
4576 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4577 if (wback && ((n == 15) || (n == t)))
4578 return false;
4579
4580 break;
4581 }
4582 default:
4583 return false;
4584 }
4585
4586 addr_t offset_addr;
4587 addr_t address;
4588 int32_t offset = 0;
4589
4590 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4591 if (!success)
4592 return false;
4593
4594 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4595 if (!success)
4596 return false;
4597
4598 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004599 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004600
4601 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4602 if (add)
4603 offset_addr = base_address + offset;
4604 else
4605 offset_addr = base_address - offset;
4606
4607 // address = if index then offset_addr else R[n];
4608 if (index)
4609 address = offset_addr;
4610 else
4611 address = base_address;
4612
4613 uint32_t data;
4614 // if t == 15 then // Only possible for encoding A1
4615 if (t == 15)
4616 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004617 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004618 else
4619 // data = R[t];
4620 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4621
4622 if (!success)
4623 return false;
4624
4625 EmulateInstruction::Context context;
4626 context.type = eContextRegisterStore;
4627
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004628 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004629 if (UnalignedSupport ()
4630 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4631 || CurrentInstrSet() == eModeARM)
4632 {
4633 // MemU[address,4] = data;
4634
4635 Register base_reg;
4636 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4637
4638 Register data_reg;
4639 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4640
4641 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004642 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004643 return false;
4644
4645 }
4646 else
4647 // MemU[address,4] = bits(32) UNKNOWN;
4648 WriteBits32UnknownToMemory (address);
4649
4650 // if wback then R[n] = offset_addr;
4651 if (wback)
4652 {
4653 context.type = eContextRegisterLoad;
4654 context.SetAddress (offset_addr);
4655 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4656 return false;
4657 }
4658
4659 }
4660 return true;
4661}
Caroline Tice73a29de2011-02-16 20:22:22 +00004662
4663bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004664EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004665{
4666#if 0
4667 if ConditionPassed() then
4668 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4669 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4670 address = if index then offset_addr else R[n];
4671 MemU[address,1] = R[t]<7:0>;
4672 if wback then R[n] = offset_addr;
4673#endif
4674
4675
4676 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004677
Greg Clayton7bc39082011-03-24 23:53:38 +00004678 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004679 {
4680 uint32_t t;
4681 uint32_t n;
4682 uint32_t imm32;
4683 bool index;
4684 bool add;
4685 bool wback;
4686 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4687 switch (encoding)
4688 {
4689 case eEncodingT1:
4690 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4691 t = Bits32 (opcode, 2, 0);
4692 n = Bits32 (opcode, 5, 3);
4693 imm32 = Bits32 (opcode, 10, 6);
4694
4695 // index = TRUE; add = TRUE; wback = FALSE;
4696 index = true;
4697 add = true;
4698 wback = false;
4699 break;
4700
4701 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004702 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004703 if (Bits32 (opcode, 19, 16) == 15)
4704 return false;
4705
4706 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4707 t = Bits32 (opcode, 15, 12);
4708 n = Bits32 (opcode, 19, 16);
4709 imm32 = Bits32 (opcode, 11, 0);
4710
4711 // index = TRUE; add = TRUE; wback = FALSE;
4712 index = true;
4713 add = true;
4714 wback = false;
4715
4716 // if BadReg(t) then UNPREDICTABLE;
4717 if (BadReg (t))
4718 return false;
4719 break;
4720
4721 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004722 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4723 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004724 if (Bits32 (opcode, 19, 16) == 15)
4725 return false;
4726
4727 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4728 t = Bits32 (opcode, 15, 12);
4729 n = Bits32 (opcode, 19, 16);
4730 imm32 = Bits32 (opcode, 7, 0);
4731
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004732 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004733 index = BitIsSet (opcode, 10);
4734 add = BitIsSet (opcode, 9);
4735 wback = BitIsSet (opcode, 8);
4736
4737 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4738 if ((BadReg (t)) || (wback && (n == t)))
4739 return false;
4740 break;
4741
4742 default:
4743 return false;
4744 }
4745
4746 addr_t offset_addr;
4747 addr_t address;
4748 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4749 if (!success)
4750 return false;
4751
4752 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4753 if (add)
4754 offset_addr = base_address + imm32;
4755 else
4756 offset_addr = base_address - imm32;
4757
4758 // address = if index then offset_addr else R[n];
4759 if (index)
4760 address = offset_addr;
4761 else
4762 address = base_address;
4763
Caroline Ticecc96eb52011-02-17 19:20:40 +00004764 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004765 Register base_reg;
4766 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4767
4768 Register data_reg;
4769 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4770
4771 EmulateInstruction::Context context;
4772 context.type = eContextRegisterStore;
4773 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4774
4775 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4776 if (!success)
4777 return false;
4778
4779 data = Bits32 (data, 7, 0);
4780
Caroline Ticecc96eb52011-02-17 19:20:40 +00004781 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004782 return false;
4783
4784 // if wback then R[n] = offset_addr;
4785 if (wback)
4786 {
4787 context.type = eContextRegisterLoad;
4788 context.SetAddress (offset_addr);
4789 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4790 return false;
4791 }
4792
4793 }
4794
4795 return true;
4796}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004797
4798// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4799// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4800bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004801EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004802{
4803#if 0
4804 if ConditionPassed() then
4805 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4806 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4807 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4808 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004809 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004810 MemU[address,2] = R[t]<15:0>;
4811 else // Can only occur before ARMv7
4812 MemU[address,2] = bits(16) UNKNOWN;
4813 if wback then R[n] = offset_addr;
4814#endif
4815
4816 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004817
Greg Clayton7bc39082011-03-24 23:53:38 +00004818 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004819 {
4820 uint32_t t;
4821 uint32_t n;
4822 uint32_t m;
4823 bool index;
4824 bool add;
4825 bool wback;
4826 ARM_ShifterType shift_t;
4827 uint32_t shift_n;
4828
4829 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4830 switch (encoding)
4831 {
4832 case eEncodingT1:
4833 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4834 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4835 t = Bits32 (opcode, 2, 0);
4836 n = Bits32 (opcode, 5, 3);
4837 m = Bits32 (opcode, 8, 6);
4838
4839 // index = TRUE; add = TRUE; wback = FALSE;
4840 index = true;
4841 add = true;
4842 wback = false;
4843
4844 // (shift_t, shift_n) = (SRType_LSL, 0);
4845 shift_t = SRType_LSL;
4846 shift_n = 0;
4847
4848 break;
4849
4850 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004851 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004852 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4853 t = Bits32 (opcode, 15, 12);
4854 n = Bits32 (opcode, 19, 16);
4855 m = Bits32 (opcode, 3, 0);
4856 if (n == 15)
4857 return false;
4858
4859 // index = TRUE; add = TRUE; wback = FALSE;
4860 index = true;
4861 add = true;
4862 wback = false;
4863
4864 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4865 shift_t = SRType_LSL;
4866 shift_n = Bits32 (opcode, 5, 4);
4867
4868 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4869 if (BadReg (t) || BadReg (m))
4870 return false;
4871
4872 break;
4873
4874 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004875 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004876 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4877 t = Bits32 (opcode, 15, 12);
4878 n = Bits32 (opcode, 19, 16);
4879 m = Bits32 (opcode, 3, 0);
4880
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004881 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004882 index = BitIsSet (opcode, 24);
4883 add = BitIsSet (opcode, 23);
4884 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4885
4886 // (shift_t, shift_n) = (SRType_LSL, 0);
4887 shift_t = SRType_LSL;
4888 shift_n = 0;
4889
4890 // if t == 15 || m == 15 then UNPREDICTABLE;
4891 if ((t == 15) || (m == 15))
4892 return false;
4893
4894 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4895 if (wback && ((n == 15) || (n == t)))
4896 return false;
4897
4898 break;
4899
4900 default:
4901 return false;
4902 }
4903
4904 uint32_t Rm = ReadCoreReg (m, &success);
4905 if (!success)
4906 return false;
4907
4908 uint32_t Rn = ReadCoreReg (n, &success);
4909 if (!success)
4910 return false;
4911
4912 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4913 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4914
4915 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4916 addr_t offset_addr;
4917 if (add)
4918 offset_addr = Rn + offset;
4919 else
4920 offset_addr = Rn - offset;
4921
4922 // address = if index then offset_addr else R[n];
4923 addr_t address;
4924 if (index)
4925 address = offset_addr;
4926 else
4927 address = Rn;
4928
4929 EmulateInstruction::Context context;
4930 context.type = eContextRegisterStore;
4931 Register base_reg;
4932 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4933 Register offset_reg;
4934 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4935
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004936 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004937 if (UnalignedSupport() || BitIsClear (address, 0))
4938 {
4939 // MemU[address,2] = R[t]<15:0>;
4940 uint32_t Rt = ReadCoreReg (t, &success);
4941 if (!success)
4942 return false;
4943
4944 EmulateInstruction::Context context;
4945 context.type = eContextRegisterStore;
4946 Register base_reg;
4947 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4948 Register offset_reg;
4949 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4950 Register data_reg;
4951 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4952 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
4953
4954 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
4955 return false;
4956 }
4957 else // Can only occur before ARMv7
4958 {
4959 // MemU[address,2] = bits(16) UNKNOWN;
4960 }
4961
4962 // if wback then R[n] = offset_addr;
4963 if (wback)
4964 {
4965 context.type = eContextAdjustBaseRegister;
4966 context.SetAddress (offset_addr);
4967 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4968 return false;
4969 }
4970 }
4971
4972 return true;
4973}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004974
Johnny Chen157b9592011-02-18 21:13:05 +00004975// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4976// and writes the result to the destination register. It can optionally update the condition flags
4977// based on the result.
4978bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004979EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00004980{
4981#if 0
4982 // ARM pseudo code...
4983 if ConditionPassed() then
4984 EncodingSpecificOperations();
4985 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4986 if d == 15 then // Can only occur for ARM encoding
4987 ALUWritePC(result); // setflags is always FALSE here
4988 else
4989 R[d] = result;
4990 if setflags then
4991 APSR.N = result<31>;
4992 APSR.Z = IsZeroBit(result);
4993 APSR.C = carry;
4994 APSR.V = overflow;
4995#endif
4996
4997 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00004998
Greg Clayton7bc39082011-03-24 23:53:38 +00004999 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005000 {
5001 uint32_t Rd, Rn;
5002 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5003 bool setflags;
5004 switch (encoding)
5005 {
5006 case eEncodingT1:
5007 Rd = Bits32(opcode, 11, 8);
5008 Rn = Bits32(opcode, 19, 16);
5009 setflags = BitIsSet(opcode, 20);
5010 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5011 if (BadReg(Rd) || BadReg(Rn))
5012 return false;
5013 break;
5014 case eEncodingA1:
5015 Rd = Bits32(opcode, 15, 12);
5016 Rn = Bits32(opcode, 19, 16);
5017 setflags = BitIsSet(opcode, 20);
5018 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5019 // TODO: Emulate SUBS PC, LR and related instructions.
5020 if (Rd == 15 && setflags)
5021 return false;
5022 break;
5023 default:
5024 return false;
5025 }
5026
5027 // Read the first operand.
5028 int32_t val1 = ReadCoreReg(Rn, &success);
5029 if (!success)
5030 return false;
5031
5032 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5033
5034 EmulateInstruction::Context context;
5035 context.type = EmulateInstruction::eContextImmediate;
5036 context.SetNoArgs ();
5037
5038 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5039 return false;
5040 }
5041 return true;
5042}
5043
5044// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5045// register value, and writes the result to the destination register. It can optionally update the
5046// condition flags based on the result.
5047bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005048EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005049{
5050#if 0
5051 // ARM pseudo code...
5052 if ConditionPassed() then
5053 EncodingSpecificOperations();
5054 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5055 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5056 if d == 15 then // Can only occur for ARM encoding
5057 ALUWritePC(result); // setflags is always FALSE here
5058 else
5059 R[d] = result;
5060 if setflags then
5061 APSR.N = result<31>;
5062 APSR.Z = IsZeroBit(result);
5063 APSR.C = carry;
5064 APSR.V = overflow;
5065#endif
5066
5067 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005068
Greg Clayton7bc39082011-03-24 23:53:38 +00005069 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005070 {
5071 uint32_t Rd, Rn, Rm;
5072 ARM_ShifterType shift_t;
5073 uint32_t shift_n; // the shift applied to the value read from Rm
5074 bool setflags;
5075 switch (encoding)
5076 {
5077 case eEncodingT1:
5078 Rd = Rn = Bits32(opcode, 2, 0);
5079 Rm = Bits32(opcode, 5, 3);
5080 setflags = !InITBlock();
5081 shift_t = SRType_LSL;
5082 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005083 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005084 case eEncodingT2:
5085 Rd = Bits32(opcode, 11, 8);
5086 Rn = Bits32(opcode, 19, 16);
5087 Rm = Bits32(opcode, 3, 0);
5088 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005089 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005090 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5091 return false;
5092 break;
5093 case eEncodingA1:
5094 Rd = Bits32(opcode, 15, 12);
5095 Rn = Bits32(opcode, 19, 16);
5096 Rm = Bits32(opcode, 3, 0);
5097 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005098 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005099 // TODO: Emulate SUBS PC, LR and related instructions.
5100 if (Rd == 15 && setflags)
5101 return false;
5102 break;
5103 default:
5104 return false;
5105 }
5106
5107 // Read the first operand.
5108 int32_t val1 = ReadCoreReg(Rn, &success);
5109 if (!success)
5110 return false;
5111
5112 // Read the second operand.
5113 int32_t val2 = ReadCoreReg(Rm, &success);
5114 if (!success)
5115 return false;
5116
5117 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5118 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5119
5120 EmulateInstruction::Context context;
5121 context.type = EmulateInstruction::eContextImmediate;
5122 context.SetNoArgs ();
5123
5124 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5125 return false;
5126 }
5127 return true;
5128}
5129
Johnny Chena695f952011-02-23 21:24:25 +00005130// This instruction adds an immediate value to the PC value to form a PC-relative address,
5131// and writes the result to the destination register.
5132bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005133EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005134{
5135#if 0
5136 // ARM pseudo code...
5137 if ConditionPassed() then
5138 EncodingSpecificOperations();
5139 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5140 if d == 15 then // Can only occur for ARM encodings
5141 ALUWritePC(result);
5142 else
5143 R[d] = result;
5144#endif
5145
5146 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005147
Greg Clayton7bc39082011-03-24 23:53:38 +00005148 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005149 {
5150 uint32_t Rd;
5151 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5152 bool add;
5153 switch (encoding)
5154 {
5155 case eEncodingT1:
5156 Rd = Bits32(opcode, 10, 8);
5157 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5158 break;
5159 case eEncodingT2:
5160 case eEncodingT3:
5161 Rd = Bits32(opcode, 11, 8);
5162 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5163 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5164 if (BadReg(Rd))
5165 return false;
5166 break;
5167 case eEncodingA1:
5168 case eEncodingA2:
5169 Rd = Bits32(opcode, 15, 12);
5170 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5171 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5172 break;
5173 default:
5174 return false;
5175 }
5176
5177 // Read the PC value.
5178 uint32_t pc = ReadCoreReg(PC_REG, &success);
5179 if (!success)
5180 return false;
5181
5182 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5183
5184 EmulateInstruction::Context context;
5185 context.type = EmulateInstruction::eContextImmediate;
5186 context.SetNoArgs ();
5187
5188 if (!WriteCoreReg(context, result, Rd))
5189 return false;
5190 }
5191 return true;
5192}
5193
Johnny Chene97c0d52011-02-18 19:32:20 +00005194// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5195// to the destination register. It can optionally update the condition flags based on the result.
5196bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005197EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005198{
5199#if 0
5200 // ARM pseudo code...
5201 if ConditionPassed() then
5202 EncodingSpecificOperations();
5203 result = R[n] AND imm32;
5204 if d == 15 then // Can only occur for ARM encoding
5205 ALUWritePC(result); // setflags is always FALSE here
5206 else
5207 R[d] = result;
5208 if setflags then
5209 APSR.N = result<31>;
5210 APSR.Z = IsZeroBit(result);
5211 APSR.C = carry;
5212 // APSR.V unchanged
5213#endif
5214
5215 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005216
Greg Clayton7bc39082011-03-24 23:53:38 +00005217 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005218 {
5219 uint32_t Rd, Rn;
5220 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5221 bool setflags;
5222 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5223 switch (encoding)
5224 {
5225 case eEncodingT1:
5226 Rd = Bits32(opcode, 11, 8);
5227 Rn = Bits32(opcode, 19, 16);
5228 setflags = BitIsSet(opcode, 20);
5229 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005230 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005231 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005232 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005233 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5234 return false;
5235 break;
5236 case eEncodingA1:
5237 Rd = Bits32(opcode, 15, 12);
5238 Rn = Bits32(opcode, 19, 16);
5239 setflags = BitIsSet(opcode, 20);
5240 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5241 // TODO: Emulate SUBS PC, LR and related instructions.
5242 if (Rd == 15 && setflags)
5243 return false;
5244 break;
5245 default:
5246 return false;
5247 }
5248
Johnny Chene97c0d52011-02-18 19:32:20 +00005249 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005250 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005251 if (!success)
5252 return false;
5253
5254 uint32_t result = val1 & imm32;
5255
5256 EmulateInstruction::Context context;
5257 context.type = EmulateInstruction::eContextImmediate;
5258 context.SetNoArgs ();
5259
5260 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5261 return false;
5262 }
5263 return true;
5264}
5265
5266// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5267// and writes the result to the destination register. It can optionally update the condition flags
5268// based on the result.
5269bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005270EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005271{
5272#if 0
5273 // ARM pseudo code...
5274 if ConditionPassed() then
5275 EncodingSpecificOperations();
5276 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5277 result = R[n] AND shifted;
5278 if d == 15 then // Can only occur for ARM encoding
5279 ALUWritePC(result); // setflags is always FALSE here
5280 else
5281 R[d] = result;
5282 if setflags then
5283 APSR.N = result<31>;
5284 APSR.Z = IsZeroBit(result);
5285 APSR.C = carry;
5286 // APSR.V unchanged
5287#endif
5288
5289 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005290
Greg Clayton7bc39082011-03-24 23:53:38 +00005291 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005292 {
5293 uint32_t Rd, Rn, Rm;
5294 ARM_ShifterType shift_t;
5295 uint32_t shift_n; // the shift applied to the value read from Rm
5296 bool setflags;
5297 uint32_t carry;
5298 switch (encoding)
5299 {
5300 case eEncodingT1:
5301 Rd = Rn = Bits32(opcode, 2, 0);
5302 Rm = Bits32(opcode, 5, 3);
5303 setflags = !InITBlock();
5304 shift_t = SRType_LSL;
5305 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005306 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005307 case eEncodingT2:
5308 Rd = Bits32(opcode, 11, 8);
5309 Rn = Bits32(opcode, 19, 16);
5310 Rm = Bits32(opcode, 3, 0);
5311 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005312 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005313 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005314 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005315 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005316 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5317 return false;
5318 break;
5319 case eEncodingA1:
5320 Rd = Bits32(opcode, 15, 12);
5321 Rn = Bits32(opcode, 19, 16);
5322 Rm = Bits32(opcode, 3, 0);
5323 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005324 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005325 // TODO: Emulate SUBS PC, LR and related instructions.
5326 if (Rd == 15 && setflags)
5327 return false;
5328 break;
5329 default:
5330 return false;
5331 }
5332
Johnny Chene97c0d52011-02-18 19:32:20 +00005333 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005334 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005335 if (!success)
5336 return false;
5337
5338 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005339 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005340 if (!success)
5341 return false;
5342
5343 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5344 uint32_t result = val1 & shifted;
5345
5346 EmulateInstruction::Context context;
5347 context.type = EmulateInstruction::eContextImmediate;
5348 context.SetNoArgs ();
5349
5350 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5351 return false;
5352 }
5353 return true;
5354}
5355
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005356// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5357// immediate value, and writes the result to the destination register. It can optionally update the
5358// condition flags based on the result.
5359bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005360EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005361{
5362#if 0
5363 // ARM pseudo code...
5364 if ConditionPassed() then
5365 EncodingSpecificOperations();
5366 result = R[n] AND NOT(imm32);
5367 if d == 15 then // Can only occur for ARM encoding
5368 ALUWritePC(result); // setflags is always FALSE here
5369 else
5370 R[d] = result;
5371 if setflags then
5372 APSR.N = result<31>;
5373 APSR.Z = IsZeroBit(result);
5374 APSR.C = carry;
5375 // APSR.V unchanged
5376#endif
5377
5378 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005379
Greg Clayton7bc39082011-03-24 23:53:38 +00005380 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005381 {
5382 uint32_t Rd, Rn;
5383 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5384 bool setflags;
5385 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5386 switch (encoding)
5387 {
5388 case eEncodingT1:
5389 Rd = Bits32(opcode, 11, 8);
5390 Rn = Bits32(opcode, 19, 16);
5391 setflags = BitIsSet(opcode, 20);
5392 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5393 if (BadReg(Rd) || BadReg(Rn))
5394 return false;
5395 break;
5396 case eEncodingA1:
5397 Rd = Bits32(opcode, 15, 12);
5398 Rn = Bits32(opcode, 19, 16);
5399 setflags = BitIsSet(opcode, 20);
5400 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005401 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005402 // TODO: Emulate SUBS PC, LR and related instructions.
5403 if (Rd == 15 && setflags)
5404 return false;
5405 break;
5406 default:
5407 return false;
5408 }
5409
5410 // Read the first operand.
5411 uint32_t val1 = ReadCoreReg(Rn, &success);
5412 if (!success)
5413 return false;
5414
5415 uint32_t result = val1 & ~imm32;
5416
5417 EmulateInstruction::Context context;
5418 context.type = EmulateInstruction::eContextImmediate;
5419 context.SetNoArgs ();
5420
5421 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5422 return false;
5423 }
5424 return true;
5425}
5426
5427// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5428// optionally-shifted register value, and writes the result to the destination register.
5429// It can optionally update the condition flags based on the result.
5430bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005431EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005432{
5433#if 0
5434 // ARM pseudo code...
5435 if ConditionPassed() then
5436 EncodingSpecificOperations();
5437 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5438 result = R[n] AND NOT(shifted);
5439 if d == 15 then // Can only occur for ARM encoding
5440 ALUWritePC(result); // setflags is always FALSE here
5441 else
5442 R[d] = result;
5443 if setflags then
5444 APSR.N = result<31>;
5445 APSR.Z = IsZeroBit(result);
5446 APSR.C = carry;
5447 // APSR.V unchanged
5448#endif
5449
5450 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005451
Greg Clayton7bc39082011-03-24 23:53:38 +00005452 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005453 {
5454 uint32_t Rd, Rn, Rm;
5455 ARM_ShifterType shift_t;
5456 uint32_t shift_n; // the shift applied to the value read from Rm
5457 bool setflags;
5458 uint32_t carry;
5459 switch (encoding)
5460 {
5461 case eEncodingT1:
5462 Rd = Rn = Bits32(opcode, 2, 0);
5463 Rm = Bits32(opcode, 5, 3);
5464 setflags = !InITBlock();
5465 shift_t = SRType_LSL;
5466 shift_n = 0;
5467 break;
5468 case eEncodingT2:
5469 Rd = Bits32(opcode, 11, 8);
5470 Rn = Bits32(opcode, 19, 16);
5471 Rm = Bits32(opcode, 3, 0);
5472 setflags = BitIsSet(opcode, 20);
5473 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5474 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5475 return false;
5476 break;
5477 case eEncodingA1:
5478 Rd = Bits32(opcode, 15, 12);
5479 Rn = Bits32(opcode, 19, 16);
5480 Rm = Bits32(opcode, 3, 0);
5481 setflags = BitIsSet(opcode, 20);
5482 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005483 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005484 // TODO: Emulate SUBS PC, LR and related instructions.
5485 if (Rd == 15 && setflags)
5486 return false;
5487 break;
5488 default:
5489 return false;
5490 }
5491
5492 // Read the first operand.
5493 uint32_t val1 = ReadCoreReg(Rn, &success);
5494 if (!success)
5495 return false;
5496
5497 // Read the second operand.
5498 uint32_t val2 = ReadCoreReg(Rm, &success);
5499 if (!success)
5500 return false;
5501
5502 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5503 uint32_t result = val1 & ~shifted;
5504
5505 EmulateInstruction::Context context;
5506 context.type = EmulateInstruction::eContextImmediate;
5507 context.SetNoArgs ();
5508
5509 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5510 return false;
5511 }
5512 return true;
5513}
5514
Caroline Tice4d729c52011-02-18 00:55:53 +00005515// 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 +00005516// 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 +00005517bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005518EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005519{
5520#if 0
5521 if ConditionPassed() then
5522 EncodingSpecificOperations();
5523 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5524 address = if index then offset_addr else R[n];
5525 data = MemU[address,4];
5526 if wback then R[n] = offset_addr;
5527 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005528 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5529 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005530 R[t] = data;
5531 else // Can only apply before ARMv7
5532 R[t] = ROR(data, 8*UInt(address<1:0>));
5533#endif
5534
5535 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005536
Greg Clayton7bc39082011-03-24 23:53:38 +00005537 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005538 {
5539 const uint32_t addr_byte_size = GetAddressByteSize();
5540
5541 uint32_t t;
5542 uint32_t n;
5543 uint32_t imm32;
5544 bool index;
5545 bool add;
5546 bool wback;
5547
5548 switch (encoding)
5549 {
5550 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005551 // if Rn == '1111' then SEE LDR (literal);
5552 // if P == '0' && W == '1' then SEE LDRT;
5553 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005554 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5555 t = Bits32 (opcode, 15, 12);
5556 n = Bits32 (opcode, 19, 16);
5557 imm32 = Bits32 (opcode, 11, 0);
5558
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005559 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5560 index = BitIsSet (opcode, 24);
5561 add = BitIsSet (opcode, 23);
5562 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005563
5564 // if wback && n == t then UNPREDICTABLE;
5565 if (wback && (n == t))
5566 return false;
5567
5568 break;
5569
5570 default:
5571 return false;
5572 }
5573
5574 addr_t address;
5575 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005576 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005577 if (!success)
5578 return false;
5579
5580 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5581 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005582 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005583 else
5584 offset_addr = base_address - imm32;
5585
5586 // address = if index then offset_addr else R[n];
5587 if (index)
5588 address = offset_addr;
5589 else
5590 address = base_address;
5591
5592 // data = MemU[address,4];
5593
5594 Register base_reg;
5595 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5596
5597 EmulateInstruction::Context context;
5598 context.type = eContextRegisterLoad;
5599 context.SetRegisterPlusOffset (base_reg, address - base_address);
5600
5601 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5602 if (!success)
5603 return false;
5604
5605 // if wback then R[n] = offset_addr;
5606 if (wback)
5607 {
5608 context.type = eContextAdjustBaseRegister;
5609 context.SetAddress (offset_addr);
5610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5611 return false;
5612 }
5613
5614 // if t == 15 then
5615 if (t == 15)
5616 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005617 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005618 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5619 {
5620 // LoadWritePC (data);
5621 context.type = eContextRegisterLoad;
5622 context.SetRegisterPlusOffset (base_reg, address - base_address);
5623 LoadWritePC (context, data);
5624 }
5625 else
5626 return false;
5627 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005628 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005629 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5630 {
5631 // R[t] = data;
5632 context.type = eContextRegisterLoad;
5633 context.SetRegisterPlusOffset (base_reg, address - base_address);
5634 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5635 return false;
5636 }
5637 // else // Can only apply before ARMv7
5638 else
5639 {
5640 // R[t] = ROR(data, 8*UInt(address<1:0>));
5641 data = ROR (data, Bits32 (address, 1, 0));
5642 context.type = eContextRegisterLoad;
5643 context.SetImmediate (data);
5644 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5645 return false;
5646 }
5647
5648 }
5649 return true;
5650}
5651
Caroline Ticefe479112011-02-18 18:52:37 +00005652// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5653// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5654bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005655EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005656{
5657#if 0
5658 if ConditionPassed() then
5659 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5660 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5661 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5662 address = if index then offset_addr else R[n];
5663 data = MemU[address,4];
5664 if wback then R[n] = offset_addr;
5665 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005666 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5667 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005668 R[t] = data;
5669 else // Can only apply before ARMv7
5670 if CurrentInstrSet() == InstrSet_ARM then
5671 R[t] = ROR(data, 8*UInt(address<1:0>));
5672 else
5673 R[t] = bits(32) UNKNOWN;
5674#endif
5675
5676 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005677
Greg Clayton7bc39082011-03-24 23:53:38 +00005678 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005679 {
5680 const uint32_t addr_byte_size = GetAddressByteSize();
5681
5682 uint32_t t;
5683 uint32_t n;
5684 uint32_t m;
5685 bool index;
5686 bool add;
5687 bool wback;
5688 ARM_ShifterType shift_t;
5689 uint32_t shift_n;
5690
5691 switch (encoding)
5692 {
5693 case eEncodingT1:
5694 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5695 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5696 t = Bits32 (opcode, 2, 0);
5697 n = Bits32 (opcode, 5, 3);
5698 m = Bits32 (opcode, 8, 6);
5699
5700 // index = TRUE; add = TRUE; wback = FALSE;
5701 index = true;
5702 add = true;
5703 wback = false;
5704
5705 // (shift_t, shift_n) = (SRType_LSL, 0);
5706 shift_t = SRType_LSL;
5707 shift_n = 0;
5708
5709 break;
5710
5711 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005712 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005713 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5714 t = Bits32 (opcode, 15, 12);
5715 n = Bits32 (opcode, 19, 16);
5716 m = Bits32 (opcode, 3, 0);
5717
5718 // index = TRUE; add = TRUE; wback = FALSE;
5719 index = true;
5720 add = true;
5721 wback = false;
5722
5723 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5724 shift_t = SRType_LSL;
5725 shift_n = Bits32 (opcode, 5, 4);
5726
5727 // if BadReg(m) then UNPREDICTABLE;
5728 if (BadReg (m))
5729 return false;
5730
5731 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5732 if ((t == 15) && InITBlock() && !LastInITBlock())
5733 return false;
5734
5735 break;
5736
5737 case eEncodingA1:
5738 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005739 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005740 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5741 t = Bits32 (opcode, 15, 12);
5742 n = Bits32 (opcode, 19, 16);
5743 m = Bits32 (opcode, 3, 0);
5744
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005745 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005746 index = BitIsSet (opcode, 24);
5747 add = BitIsSet (opcode, 23);
5748 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5749
5750 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5751 uint32_t type = Bits32 (opcode, 6, 5);
5752 uint32_t imm5 = Bits32 (opcode, 11, 7);
5753 shift_n = DecodeImmShift (type, imm5, shift_t);
5754
5755 // if m == 15 then UNPREDICTABLE;
5756 if (m == 15)
5757 return false;
5758
5759 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5760 if (wback && ((n == 15) || (n == t)))
5761 return false;
5762 }
5763 break;
5764
5765
5766 default:
5767 return false;
5768 }
5769
5770 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5771 if (!success)
5772 return false;
5773
5774 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5775 if (!success)
5776 return false;
5777
5778 addr_t offset_addr;
5779 addr_t address;
5780
5781 // 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 +00005782 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005783
5784 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5785 if (add)
5786 offset_addr = Rn + offset;
5787 else
5788 offset_addr = Rn - offset;
5789
5790 // address = if index then offset_addr else R[n];
5791 if (index)
5792 address = offset_addr;
5793 else
5794 address = Rn;
5795
5796 // data = MemU[address,4];
5797 Register base_reg;
5798 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5799
5800 EmulateInstruction::Context context;
5801 context.type = eContextRegisterLoad;
5802 context.SetRegisterPlusOffset (base_reg, address - Rn);
5803
5804 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5805 if (!success)
5806 return false;
5807
5808 // if wback then R[n] = offset_addr;
5809 if (wback)
5810 {
5811 context.type = eContextAdjustBaseRegister;
5812 context.SetAddress (offset_addr);
5813 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5814 return false;
5815 }
5816
5817 // if t == 15 then
5818 if (t == 15)
5819 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005820 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005821 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5822 {
5823 context.type = eContextRegisterLoad;
5824 context.SetRegisterPlusOffset (base_reg, address - Rn);
5825 LoadWritePC (context, data);
5826 }
5827 else
5828 return false;
5829 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005830 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005831 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5832 {
5833 // R[t] = data;
5834 context.type = eContextRegisterLoad;
5835 context.SetRegisterPlusOffset (base_reg, address - Rn);
5836 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5837 return false;
5838 }
5839 else // Can only apply before ARMv7
5840 {
5841 // if CurrentInstrSet() == InstrSet_ARM then
5842 if (CurrentInstrSet () == eModeARM)
5843 {
5844 // R[t] = ROR(data, 8*UInt(address<1:0>));
5845 data = ROR (data, Bits32 (address, 1, 0));
5846 context.type = eContextRegisterLoad;
5847 context.SetImmediate (data);
5848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5849 return false;
5850 }
5851 else
5852 {
5853 // R[t] = bits(32) UNKNOWN;
5854 WriteBits32Unknown (t);
5855 }
5856 }
5857 }
5858 return true;
5859}
Caroline Tice21b604b2011-02-18 21:06:04 +00005860
5861// LDRB (immediate, Thumb)
5862bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005863EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005864{
5865#if 0
5866 if ConditionPassed() then
5867 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5868 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5869 address = if index then offset_addr else R[n];
5870 R[t] = ZeroExtend(MemU[address,1], 32);
5871 if wback then R[n] = offset_addr;
5872#endif
5873
5874 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005875
Greg Clayton7bc39082011-03-24 23:53:38 +00005876 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005877 {
5878 uint32_t t;
5879 uint32_t n;
5880 uint32_t imm32;
5881 bool index;
5882 bool add;
5883 bool wback;
5884
5885 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5886 switch (encoding)
5887 {
5888 case eEncodingT1:
5889 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5890 t = Bits32 (opcode, 2, 0);
5891 n = Bits32 (opcode, 5, 3);
5892 imm32 = Bits32 (opcode, 10, 6);
5893
5894 // index = TRUE; add = TRUE; wback = FALSE;
5895 index = true;
5896 add = true;
5897 wback= false;
5898
5899 break;
5900
5901 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005902 // if Rt == '1111' then SEE PLD;
5903 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00005904 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5905 t = Bits32 (opcode, 15, 12);
5906 n = Bits32 (opcode, 19, 16);
5907 imm32 = Bits32 (opcode, 11, 0);
5908
5909 // index = TRUE; add = TRUE; wback = FALSE;
5910 index = true;
5911 add = true;
5912 wback = false;
5913
5914 // if t == 13 then UNPREDICTABLE;
5915 if (t == 13)
5916 return false;
5917
5918 break;
5919
5920 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005921 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
5922 // if Rn == '1111' then SEE LDRB (literal);
5923 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
5924 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00005925 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5926 return false;
5927
5928 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5929 t = Bits32 (opcode, 15, 12);
5930 n = Bits32 (opcode, 19, 16);
5931 imm32 = Bits32 (opcode, 7, 0);
5932
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005933 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00005934 index = BitIsSet (opcode, 10);
5935 add = BitIsSet (opcode, 9);
5936 wback = BitIsSet (opcode, 8);
5937
5938 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5939 if (BadReg (t) || (wback && (n == t)))
5940 return false;
5941
5942 break;
5943
5944 default:
5945 return false;
5946 }
5947
5948 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5949 if (!success)
5950 return false;
5951
5952 addr_t address;
5953 addr_t offset_addr;
5954
5955 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5956 if (add)
5957 offset_addr = Rn + imm32;
5958 else
5959 offset_addr = Rn - imm32;
5960
5961 // address = if index then offset_addr else R[n];
5962 if (index)
5963 address = offset_addr;
5964 else
5965 address = Rn;
5966
5967 // R[t] = ZeroExtend(MemU[address,1], 32);
5968 Register base_reg;
5969 Register data_reg;
5970 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5971 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5972
5973 EmulateInstruction::Context context;
5974 context.type = eContextRegisterLoad;
5975 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5976
5977 uint64_t data = MemURead (context, address, 1, 0, &success);
5978 if (!success)
5979 return false;
5980
5981 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5982 return false;
5983
5984 // if wback then R[n] = offset_addr;
5985 if (wback)
5986 {
5987 context.type = eContextAdjustBaseRegister;
5988 context.SetAddress (offset_addr);
5989 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5990 return false;
5991 }
5992 }
5993 return true;
5994}
Caroline Ticef55261f2011-02-18 22:24:22 +00005995
5996// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5997// zero-extends it to form a 32-bit word and writes it to a register.
5998bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005999EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006000{
6001#if 0
6002 if ConditionPassed() then
6003 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6004 base = Align(PC,4);
6005 address = if add then (base + imm32) else (base - imm32);
6006 R[t] = ZeroExtend(MemU[address,1], 32);
6007#endif
6008
6009 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006010
Greg Clayton7bc39082011-03-24 23:53:38 +00006011 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006012 {
6013 uint32_t t;
6014 uint32_t imm32;
6015 bool add;
6016 switch (encoding)
6017 {
6018 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006019 // if Rt == '1111' then SEE PLD;
6020 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006021 t = Bits32 (opcode, 15, 12);
6022 imm32 = Bits32 (opcode, 11, 0);
6023 add = BitIsSet (opcode, 23);
6024
6025 // if t == 13 then UNPREDICTABLE;
6026 if (t == 13)
6027 return false;
6028
6029 break;
6030
6031 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006032 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006033 t = Bits32 (opcode, 15, 12);
6034 imm32 = Bits32 (opcode, 11, 0);
6035 add = BitIsSet (opcode, 23);
6036
6037 // if t == 15 then UNPREDICTABLE;
6038 if (t == 15)
6039 return false;
6040 break;
6041
6042 default:
6043 return false;
6044 }
6045
6046 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006047 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006048 if (!success)
6049 return false;
6050
6051 uint32_t base = AlignPC (pc_val);
6052
6053 addr_t address;
6054 // address = if add then (base + imm32) else (base - imm32);
6055 if (add)
6056 address = base + imm32;
6057 else
6058 address = base - imm32;
6059
6060 // R[t] = ZeroExtend(MemU[address,1], 32);
6061 EmulateInstruction::Context context;
6062 context.type = eContextRelativeBranchImmediate;
6063 context.SetImmediate (address - base);
6064
6065 uint64_t data = MemURead (context, address, 1, 0, &success);
6066 if (!success)
6067 return false;
6068
6069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6070 return false;
6071 }
6072 return true;
6073}
Caroline Tice30fec122011-02-18 23:52:21 +00006074
6075// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6076// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6077// optionally be shifted.
6078bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006079EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006080{
6081#if 0
6082 if ConditionPassed() then
6083 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6084 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6085 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6086 address = if index then offset_addr else R[n];
6087 R[t] = ZeroExtend(MemU[address,1],32);
6088 if wback then R[n] = offset_addr;
6089#endif
6090
6091 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006092
Greg Clayton7bc39082011-03-24 23:53:38 +00006093 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006094 {
6095 uint32_t t;
6096 uint32_t n;
6097 uint32_t m;
6098 bool index;
6099 bool add;
6100 bool wback;
6101 ARM_ShifterType shift_t;
6102 uint32_t shift_n;
6103
6104 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6105 switch (encoding)
6106 {
6107 case eEncodingT1:
6108 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6109 t = Bits32 (opcode, 2, 0);
6110 n = Bits32 (opcode, 5, 3);
6111 m = Bits32 (opcode, 8, 6);
6112
6113 // index = TRUE; add = TRUE; wback = FALSE;
6114 index = true;
6115 add = true;
6116 wback = false;
6117
6118 // (shift_t, shift_n) = (SRType_LSL, 0);
6119 shift_t = SRType_LSL;
6120 shift_n = 0;
6121 break;
6122
6123 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006124 // if Rt == '1111' then SEE PLD;
6125 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006126 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6127 t = Bits32 (opcode, 15, 12);
6128 n = Bits32 (opcode, 19, 16);
6129 m = Bits32 (opcode, 3, 0);
6130
6131 // index = TRUE; add = TRUE; wback = FALSE;
6132 index = true;
6133 add = true;
6134 wback = false;
6135
6136 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6137 shift_t = SRType_LSL;
6138 shift_n = Bits32 (opcode, 5, 4);
6139
6140 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6141 if ((t == 13) || BadReg (m))
6142 return false;
6143 break;
6144
6145 case eEncodingA1:
6146 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006147 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006148 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6149 t = Bits32 (opcode, 15, 12);
6150 n = Bits32 (opcode, 19, 16);
6151 m = Bits32 (opcode, 3, 0);
6152
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006153 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006154 index = BitIsSet (opcode, 24);
6155 add = BitIsSet (opcode, 23);
6156 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6157
6158 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6159 uint32_t type = Bits32 (opcode, 6, 5);
6160 uint32_t imm5 = Bits32 (opcode, 11, 7);
6161 shift_n = DecodeImmShift (type, imm5, shift_t);
6162
6163 // if t == 15 || m == 15 then UNPREDICTABLE;
6164 if ((t == 15) || (m == 15))
6165 return false;
6166
6167 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6168 if (wback && ((n == 15) || (n == t)))
6169 return false;
6170 }
6171 break;
6172
6173 default:
6174 return false;
6175 }
6176
6177 addr_t offset_addr;
6178 addr_t address;
6179
6180 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6181 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6182 if (!success)
6183 return false;
6184
6185 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6186
6187 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6188 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6189 if (!success)
6190 return false;
6191
6192 if (add)
6193 offset_addr = Rn + offset;
6194 else
6195 offset_addr = Rn - offset;
6196
6197 // address = if index then offset_addr else R[n];
6198 if (index)
6199 address = offset_addr;
6200 else
6201 address = Rn;
6202
6203 // R[t] = ZeroExtend(MemU[address,1],32);
6204 Register base_reg;
6205 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6206
6207 EmulateInstruction::Context context;
6208 context.type = eContextRegisterLoad;
6209 context.SetRegisterPlusOffset (base_reg, address - Rn);
6210
6211 uint64_t data = MemURead (context, address, 1, 0, &success);
6212 if (!success)
6213 return false;
6214
6215 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6216 return false;
6217
6218 // if wback then R[n] = offset_addr;
6219 if (wback)
6220 {
6221 context.type = eContextAdjustBaseRegister;
6222 context.SetAddress (offset_addr);
6223 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6224 return false;
6225 }
6226 }
6227 return true;
6228}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006229
6230// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6231// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6232// post-indexed, or pre-indexed addressing.
6233bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006234EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006235{
6236#if 0
6237 if ConditionPassed() then
6238 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6239 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6240 address = if index then offset_addr else R[n];
6241 data = MemU[address,2];
6242 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006243 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006244 R[t] = ZeroExtend(data, 32);
6245 else // Can only apply before ARMv7
6246 R[t] = bits(32) UNKNOWN;
6247#endif
6248
6249
6250 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006251
Greg Clayton7bc39082011-03-24 23:53:38 +00006252 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006253 {
6254 uint32_t t;
6255 uint32_t n;
6256 uint32_t imm32;
6257 bool index;
6258 bool add;
6259 bool wback;
6260
6261 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6262 switch (encoding)
6263 {
6264 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006265 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006266 t = Bits32 (opcode, 2, 0);
6267 n = Bits32 (opcode, 5, 3);
6268 imm32 = Bits32 (opcode, 10, 6) << 1;
6269
6270 // index = TRUE; add = TRUE; wback = FALSE;
6271 index = true;
6272 add = true;
6273 wback = false;
6274
6275 break;
6276
6277 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006278 // if Rt == '1111' then SEE "Unallocated memory hints";
6279 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006280 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6281 t = Bits32 (opcode, 15, 12);
6282 n = Bits32 (opcode, 19, 16);
6283 imm32 = Bits32 (opcode, 11, 0);
6284
6285 // index = TRUE; add = TRUE; wback = FALSE;
6286 index = true;
6287 add = true;
6288 wback = false;
6289
6290 // if t == 13 then UNPREDICTABLE;
6291 if (t == 13)
6292 return false;
6293 break;
6294
6295 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006296 // if Rn == '1111' then SEE LDRH (literal);
6297 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6298 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6299 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006300 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6301 return false;
6302
6303 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6304 t = Bits32 (opcode, 15, 12);
6305 n = Bits32 (opcode, 19, 16);
6306 imm32 = Bits32 (opcode, 7, 0);
6307
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006308 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006309 index = BitIsSet (opcode, 10);
6310 add = BitIsSet (opcode, 9);
6311 wback = BitIsSet (opcode, 8);
6312
6313 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6314 if (BadReg (t) || (wback && (n == t)))
6315 return false;
6316 break;
6317
6318 default:
6319 return false;
6320 }
6321
6322 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6323 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6324 if (!success)
6325 return false;
6326
6327 addr_t offset_addr;
6328 addr_t address;
6329
6330 if (add)
6331 offset_addr = Rn + imm32;
6332 else
6333 offset_addr = Rn - imm32;
6334
6335 // address = if index then offset_addr else R[n];
6336 if (index)
6337 address = offset_addr;
6338 else
6339 address = Rn;
6340
6341 // data = MemU[address,2];
6342 Register base_reg;
6343 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6344
6345 EmulateInstruction::Context context;
6346 context.type = eContextRegisterLoad;
6347 context.SetRegisterPlusOffset (base_reg, address - Rn);
6348
6349 uint64_t data = MemURead (context, address, 2, 0, &success);
6350 if (!success)
6351 return false;
6352
6353 // if wback then R[n] = offset_addr;
6354 if (wback)
6355 {
6356 context.type = eContextAdjustBaseRegister;
6357 context.SetAddress (offset_addr);
6358 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6359 return false;
6360 }
6361
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006362 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006363 if (UnalignedSupport () || BitIsClear (address, 0))
6364 {
6365 // R[t] = ZeroExtend(data, 32);
6366 context.type = eContextRegisterLoad;
6367 context.SetRegisterPlusOffset (base_reg, address - Rn);
6368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6369 return false;
6370 }
6371 else // Can only apply before ARMv7
6372 {
6373 // R[t] = bits(32) UNKNOWN;
6374 WriteBits32Unknown (t);
6375 }
6376 }
6377 return true;
6378}
Caroline Ticefe479112011-02-18 18:52:37 +00006379
Caroline Tice952b5382011-02-28 23:15:24 +00006380// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6381// zero-extends it to form a 32-bit word, and writes it to a register.
6382bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006383EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006384{
6385#if 0
6386 if ConditionPassed() then
6387 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6388 base = Align(PC,4);
6389 address = if add then (base + imm32) else (base - imm32);
6390 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006391 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006392 R[t] = ZeroExtend(data, 32);
6393 else // Can only apply before ARMv7
6394 R[t] = bits(32) UNKNOWN;
6395#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006396
Caroline Tice952b5382011-02-28 23:15:24 +00006397 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006398
Greg Clayton7bc39082011-03-24 23:53:38 +00006399 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006400 {
6401 uint32_t t;
6402 uint32_t imm32;
6403 bool add;
6404
6405 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6406 switch (encoding)
6407 {
6408 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006409 // if Rt == '1111' then SEE "Unallocated memory hints";
6410 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006411 t = Bits32 (opcode, 15, 12);
6412 imm32 = Bits32 (opcode, 11, 0);
6413 add = BitIsSet (opcode, 23);
6414
6415 // if t == 13 then UNPREDICTABLE;
6416 if (t == 13)
6417 return false;
6418
6419 break;
6420
6421 case eEncodingA1:
6422 {
6423 uint32_t imm4H = Bits32 (opcode, 11, 8);
6424 uint32_t imm4L = Bits32 (opcode, 3, 0);
6425
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006426 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006427 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006428 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006429 add = BitIsSet (opcode, 23);
6430
6431 // if t == 15 then UNPREDICTABLE;
6432 if (t == 15)
6433 return false;
6434 break;
6435 }
6436
6437 default:
6438 return false;
6439 }
6440
6441 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006442 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006443 if (!success)
6444 return false;
6445
6446 addr_t base = AlignPC (pc_value);
6447 addr_t address;
6448
6449 // address = if add then (base + imm32) else (base - imm32);
6450 if (add)
6451 address = base + imm32;
6452 else
6453 address = base - imm32;
6454
6455 // data = MemU[address,2];
6456 Register base_reg;
6457 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6458
6459 EmulateInstruction::Context context;
6460 context.type = eContextRegisterLoad;
6461 context.SetRegisterPlusOffset (base_reg, address - base);
6462
6463 uint64_t data = MemURead (context, address, 2, 0, &success);
6464 if (!success)
6465 return false;
6466
6467
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006468 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006469 if (UnalignedSupport () || BitIsClear (address, 0))
6470 {
6471 // R[t] = ZeroExtend(data, 32);
6472 context.type = eContextRegisterLoad;
6473 context.SetRegisterPlusOffset (base_reg, address - base);
6474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6475 return false;
6476
6477 }
6478 else // Can only apply before ARMv7
6479 {
6480 // R[t] = bits(32) UNKNOWN;
6481 WriteBits32Unknown (t);
6482 }
6483 }
6484 return true;
6485}
6486
Caroline Tice0e6bc952011-03-01 18:00:42 +00006487// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6488// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6489// be shifted left by 0, 1, 2, or 3 bits.
6490bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006491EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006492{
6493#if 0
6494 if ConditionPassed() then
6495 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6496 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6497 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6498 address = if index then offset_addr else R[n];
6499 data = MemU[address,2];
6500 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006501 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006502 R[t] = ZeroExtend(data, 32);
6503 else // Can only apply before ARMv7
6504 R[t] = bits(32) UNKNOWN;
6505#endif
6506
6507 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006508
Greg Clayton7bc39082011-03-24 23:53:38 +00006509 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006510 {
6511 uint32_t t;
6512 uint32_t n;
6513 uint32_t m;
6514 bool index;
6515 bool add;
6516 bool wback;
6517 ARM_ShifterType shift_t;
6518 uint32_t shift_n;
6519
6520 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6521 switch (encoding)
6522 {
6523 case eEncodingT1:
6524 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6525 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6526 t = Bits32 (opcode, 2, 0);
6527 n = Bits32 (opcode, 5, 3);
6528 m = Bits32 (opcode, 8, 6);
6529
6530 // index = TRUE; add = TRUE; wback = FALSE;
6531 index = true;
6532 add = true;
6533 wback = false;
6534
6535 // (shift_t, shift_n) = (SRType_LSL, 0);
6536 shift_t = SRType_LSL;
6537 shift_n = 0;
6538
6539 break;
6540
6541 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006542 // if Rn == '1111' then SEE LDRH (literal);
6543 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006544 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6545 t = Bits32 (opcode, 15, 12);
6546 n = Bits32 (opcode, 19, 16);
6547 m = Bits32 (opcode, 3, 0);
6548
6549 // index = TRUE; add = TRUE; wback = FALSE;
6550 index = true;
6551 add = true;
6552 wback = false;
6553
6554 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6555 shift_t = SRType_LSL;
6556 shift_n = Bits32 (opcode, 5, 4);
6557
6558 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6559 if ((t == 13) || BadReg (m))
6560 return false;
6561 break;
6562
6563 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006564 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006565 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6566 t = Bits32 (opcode, 15, 12);
6567 n = Bits32 (opcode, 19, 16);
6568 m = Bits32 (opcode, 3, 0);
6569
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006570 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006571 index = BitIsSet (opcode, 24);
6572 add = BitIsSet (opcode, 23);
6573 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6574
6575 // (shift_t, shift_n) = (SRType_LSL, 0);
6576 shift_t = SRType_LSL;
6577 shift_n = 0;
6578
6579 // if t == 15 || m == 15 then UNPREDICTABLE;
6580 if ((t == 15) || (m == 15))
6581 return false;
6582
6583 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6584 if (wback && ((n == 15) || (n == t)))
6585 return false;
6586
6587 break;
6588
6589 default:
6590 return false;
6591 }
6592
6593 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6594
6595 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6596 if (!success)
6597 return false;
6598
6599 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6600
6601 addr_t offset_addr;
6602 addr_t address;
6603
6604 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6605 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6606 if (!success)
6607 return false;
6608
6609 if (add)
6610 offset_addr = Rn + offset;
6611 else
6612 offset_addr = Rn - offset;
6613
6614 // address = if index then offset_addr else R[n];
6615 if (index)
6616 address = offset_addr;
6617 else
6618 address = Rn;
6619
6620 // data = MemU[address,2];
6621 Register base_reg;
6622 Register offset_reg;
6623 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6624 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6625
6626 EmulateInstruction::Context context;
6627 context.type = eContextRegisterLoad;
6628 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6629 uint64_t data = MemURead (context, address, 2, 0, &success);
6630 if (!success)
6631 return false;
6632
6633 // if wback then R[n] = offset_addr;
6634 if (wback)
6635 {
6636 context.type = eContextAdjustBaseRegister;
6637 context.SetAddress (offset_addr);
6638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6639 return false;
6640 }
6641
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006642 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006643 if (UnalignedSupport() || BitIsClear (address, 0))
6644 {
6645 // R[t] = ZeroExtend(data, 32);
6646 context.type = eContextRegisterLoad;
6647 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6648 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6649 return false;
6650 }
6651 else // Can only apply before ARMv7
6652 {
6653 // R[t] = bits(32) UNKNOWN;
6654 WriteBits32Unknown (t);
6655 }
6656 }
6657 return true;
6658}
6659
Caroline Ticea5e28af2011-03-01 21:53:03 +00006660// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6661// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6662// or pre-indexed addressing.
6663bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006664EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006665{
6666#if 0
6667 if ConditionPassed() then
6668 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6669 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6670 address = if index then offset_addr else R[n];
6671 R[t] = SignExtend(MemU[address,1], 32);
6672 if wback then R[n] = offset_addr;
6673#endif
6674
6675 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006676
Greg Clayton7bc39082011-03-24 23:53:38 +00006677 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006678 {
6679 uint32_t t;
6680 uint32_t n;
6681 uint32_t imm32;
6682 bool index;
6683 bool add;
6684 bool wback;
6685
6686 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6687 switch (encoding)
6688 {
6689 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006690 // if Rt == '1111' then SEE PLI;
6691 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6693 t = Bits32 (opcode, 15, 12);
6694 n = Bits32 (opcode, 19, 16);
6695 imm32 = Bits32 (opcode, 11, 0);
6696
6697 // index = TRUE; add = TRUE; wback = FALSE;
6698 index = true;
6699 add = true;
6700 wback = false;
6701
6702 // if t == 13 then UNPREDICTABLE;
6703 if (t == 13)
6704 return false;
6705
6706 break;
6707
6708 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006709 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6710 // if Rn == '1111' then SEE LDRSB (literal);
6711 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6712 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006713 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6714 return false;
6715
6716 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6717 t = Bits32 (opcode, 15, 12);
6718 n = Bits32 (opcode, 19, 16);
6719 imm32 = Bits32 (opcode, 7, 0);
6720
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006721 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006722 index = BitIsSet (opcode, 10);
6723 add = BitIsSet (opcode, 9);
6724 wback = BitIsSet (opcode, 8);
6725
6726 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006727 if (((t == 13) || ((t == 15)
6728 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6729 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006730 return false;
6731
6732 break;
6733
6734 case eEncodingA1:
6735 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006736 // if Rn == '1111' then SEE LDRSB (literal);
6737 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006738 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6739 t = Bits32 (opcode, 15, 12);
6740 n = Bits32 (opcode, 19, 16);
6741
6742 uint32_t imm4H = Bits32 (opcode, 11, 8);
6743 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006744 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006745
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006746 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006747 index = BitIsSet (opcode, 24);
6748 add = BitIsSet (opcode, 23);
6749 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6750
6751 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6752 if ((t == 15) || (wback && (n == t)))
6753 return false;
6754
6755 break;
6756 }
6757
6758 default:
6759 return false;
6760 }
6761
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006762 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006763 if (!success)
6764 return false;
6765
6766 addr_t offset_addr;
6767 addr_t address;
6768
6769 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6770 if (add)
6771 offset_addr = Rn + imm32;
6772 else
6773 offset_addr = Rn - imm32;
6774
6775 // address = if index then offset_addr else R[n];
6776 if (index)
6777 address = offset_addr;
6778 else
6779 address = Rn;
6780
6781 // R[t] = SignExtend(MemU[address,1], 32);
6782 Register base_reg;
6783 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6784
6785 EmulateInstruction::Context context;
6786 context.type = eContextRegisterLoad;
6787 context.SetRegisterPlusOffset (base_reg, address - Rn);
6788
6789 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6790 if (!success)
6791 return false;
6792
6793 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6795 return false;
6796
6797 // if wback then R[n] = offset_addr;
6798 if (wback)
6799 {
6800 context.type = eContextAdjustBaseRegister;
6801 context.SetAddress (offset_addr);
6802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6803 return false;
6804 }
6805 }
6806
6807 return true;
6808}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006809
Caroline Tice5f593912011-03-01 22:25:17 +00006810// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6811// sign-extends it to form a 32-bit word, and writes tit to a register.
6812bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006813EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006814{
6815#if 0
6816 if ConditionPassed() then
6817 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6818 base = Align(PC,4);
6819 address = if add then (base + imm32) else (base - imm32);
6820 R[t] = SignExtend(MemU[address,1], 32);
6821#endif
6822
6823 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006824
Greg Clayton7bc39082011-03-24 23:53:38 +00006825 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006826 {
6827 uint32_t t;
6828 uint32_t imm32;
6829 bool add;
6830
6831 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6832 switch (encoding)
6833 {
6834 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006835 // if Rt == '1111' then SEE PLI;
6836 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006837 t = Bits32 (opcode, 15, 12);
6838 imm32 = Bits32 (opcode, 11, 0);
6839 add = BitIsSet (opcode, 23);
6840
6841 // if t == 13 then UNPREDICTABLE;
6842 if (t == 13)
6843 return false;
6844
6845 break;
6846
6847 case eEncodingA1:
6848 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006849 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006850 t = Bits32 (opcode, 15, 12);
6851 uint32_t imm4H = Bits32 (opcode, 11, 8);
6852 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006853 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006854 add = BitIsSet (opcode, 23);
6855
6856 // if t == 15 then UNPREDICTABLE;
6857 if (t == 15)
6858 return false;
6859
6860 break;
6861 }
6862
6863 default:
6864 return false;
6865 }
6866
6867 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006868 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006869 if (!success)
6870 return false;
6871 uint64_t base = AlignPC (pc_value);
6872
6873 // address = if add then (base + imm32) else (base - imm32);
6874 addr_t address;
6875 if (add)
6876 address = base + imm32;
6877 else
6878 address = base - imm32;
6879
6880 // R[t] = SignExtend(MemU[address,1], 32);
6881 Register base_reg;
6882 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6883
6884 EmulateInstruction::Context context;
6885 context.type = eContextRegisterLoad;
6886 context.SetRegisterPlusOffset (base_reg, address - base);
6887
6888 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6889 if (!success)
6890 return false;
6891
6892 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6893 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6894 return false;
6895 }
6896 return true;
6897}
6898
Caroline Tice672f3112011-03-01 23:55:59 +00006899// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6900// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6901// shifted left by 0, 1, 2, or 3 bits.
6902bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006903EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00006904{
6905#if 0
6906 if ConditionPassed() then
6907 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6908 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6909 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6910 address = if index then offset_addr else R[n];
6911 R[t] = SignExtend(MemU[address,1], 32);
6912 if wback then R[n] = offset_addr;
6913#endif
6914
6915 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00006916
Greg Clayton7bc39082011-03-24 23:53:38 +00006917 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00006918 {
6919 uint32_t t;
6920 uint32_t n;
6921 uint32_t m;
6922 bool index;
6923 bool add;
6924 bool wback;
6925 ARM_ShifterType shift_t;
6926 uint32_t shift_n;
6927
6928 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6929 switch (encoding)
6930 {
6931 case eEncodingT1:
6932 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6933 t = Bits32 (opcode, 2, 0);
6934 n = Bits32 (opcode, 5, 3);
6935 m = Bits32 (opcode, 8, 6);
6936
6937 // index = TRUE; add = TRUE; wback = FALSE;
6938 index = true;
6939 add = true;
6940 wback = false;
6941
6942 // (shift_t, shift_n) = (SRType_LSL, 0);
6943 shift_t = SRType_LSL;
6944 shift_n = 0;
6945
6946 break;
6947
6948 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006949 // if Rt == '1111' then SEE PLI;
6950 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00006951 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6952 t = Bits32 (opcode, 15, 12);
6953 n = Bits32 (opcode, 19, 16);
6954 m = Bits32 (opcode, 3, 0);
6955
6956 // index = TRUE; add = TRUE; wback = FALSE;
6957 index = true;
6958 add = true;
6959 wback = false;
6960
6961 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6962 shift_t = SRType_LSL;
6963 shift_n = Bits32 (opcode, 5, 4);
6964
6965 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6966 if ((t == 13) || BadReg (m))
6967 return false;
6968 break;
6969
6970 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006971 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00006972 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6973 t = Bits32 (opcode, 15, 12);
6974 n = Bits32 (opcode, 19, 16);
6975 m = Bits32 (opcode, 3, 0);
6976
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006977 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00006978 index = BitIsSet (opcode, 24);
6979 add = BitIsSet (opcode, 23);
6980 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6981
6982 // (shift_t, shift_n) = (SRType_LSL, 0);
6983 shift_t = SRType_LSL;
6984 shift_n = 0;
6985
6986 // if t == 15 || m == 15 then UNPREDICTABLE;
6987 if ((t == 15) || (m == 15))
6988 return false;
6989
6990 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6991 if (wback && ((n == 15) || (n == t)))
6992 return false;
6993 break;
6994
6995 default:
6996 return false;
6997 }
6998
6999 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7000 if (!success)
7001 return false;
7002
7003 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7004 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7005
7006 addr_t offset_addr;
7007 addr_t address;
7008
7009 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7010 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7011 if (!success)
7012 return false;
7013
7014 if (add)
7015 offset_addr = Rn + offset;
7016 else
7017 offset_addr = Rn - offset;
7018
7019 // address = if index then offset_addr else R[n];
7020 if (index)
7021 address = offset_addr;
7022 else
7023 address = Rn;
7024
7025 // R[t] = SignExtend(MemU[address,1], 32);
7026 Register base_reg;
7027 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7028 Register offset_reg;
7029 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7030
7031 EmulateInstruction::Context context;
7032 context.type = eContextRegisterLoad;
7033 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7034
7035 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7036 if (!success)
7037 return false;
7038
7039 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7040 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7041 return false;
7042
7043 // if wback then R[n] = offset_addr;
7044 if (wback)
7045 {
7046 context.type = eContextAdjustBaseRegister;
7047 context.SetAddress (offset_addr);
7048 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7049 return false;
7050 }
7051 }
7052 return true;
7053}
7054
Caroline Tice78fb5632011-03-02 00:39:42 +00007055// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7056// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7057// pre-indexed addressing.
7058bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007059EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007060{
7061#if 0
7062 if ConditionPassed() then
7063 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7064 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7065 address = if index then offset_addr else R[n];
7066 data = MemU[address,2];
7067 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007068 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007069 R[t] = SignExtend(data, 32);
7070 else // Can only apply before ARMv7
7071 R[t] = bits(32) UNKNOWN;
7072#endif
7073
7074 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007075
Greg Clayton7bc39082011-03-24 23:53:38 +00007076 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007077 {
7078 uint32_t t;
7079 uint32_t n;
7080 uint32_t imm32;
7081 bool index;
7082 bool add;
7083 bool wback;
7084
7085 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7086 switch (encoding)
7087 {
7088 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007089 // if Rn == '1111' then SEE LDRSH (literal);
7090 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007091 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7092 t = Bits32 (opcode, 15, 12);
7093 n = Bits32 (opcode, 19, 16);
7094 imm32 = Bits32 (opcode, 11, 0);
7095
7096 // index = TRUE; add = TRUE; wback = FALSE;
7097 index = true;
7098 add = true;
7099 wback = false;
7100
7101 // if t == 13 then UNPREDICTABLE;
7102 if (t == 13)
7103 return false;
7104
7105 break;
7106
7107 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007108 // if Rn == '1111' then SEE LDRSH (literal);
7109 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7110 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7111 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007112 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7113 return false;
7114
7115 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7116 t = Bits32 (opcode, 15, 12);
7117 n = Bits32 (opcode, 19, 16);
7118 imm32 = Bits32 (opcode, 7, 0);
7119
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007120 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007121 index = BitIsSet (opcode, 10);
7122 add = BitIsSet (opcode, 9);
7123 wback = BitIsSet (opcode, 8);
7124
7125 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7126 if (BadReg (t) || (wback && (n == t)))
7127 return false;
7128
7129 break;
7130
7131 case eEncodingA1:
7132 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007133 // if Rn == '1111' then SEE LDRSH (literal);
7134 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007135 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7136 t = Bits32 (opcode, 15, 12);
7137 n = Bits32 (opcode, 19, 16);
7138 uint32_t imm4H = Bits32 (opcode, 11,8);
7139 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007140 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007141
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007142 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007143 index = BitIsSet (opcode, 24);
7144 add = BitIsSet (opcode, 23);
7145 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7146
7147 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7148 if ((t == 15) || (wback && (n == t)))
7149 return false;
7150
7151 break;
7152 }
7153
7154 default:
7155 return false;
7156 }
7157
7158 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7159 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7160 if (!success)
7161 return false;
7162
7163 addr_t offset_addr;
7164 if (add)
7165 offset_addr = Rn + imm32;
7166 else
7167 offset_addr = Rn - imm32;
7168
7169 // address = if index then offset_addr else R[n];
7170 addr_t address;
7171 if (index)
7172 address = offset_addr;
7173 else
7174 address = Rn;
7175
7176 // data = MemU[address,2];
7177 Register base_reg;
7178 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7179
7180 EmulateInstruction::Context context;
7181 context.type = eContextRegisterLoad;
7182 context.SetRegisterPlusOffset (base_reg, address - Rn);
7183
7184 uint64_t data = MemURead (context, address, 2, 0, &success);
7185 if (!success)
7186 return false;
7187
7188 // if wback then R[n] = offset_addr;
7189 if (wback)
7190 {
7191 context.type = eContextAdjustBaseRegister;
7192 context.SetAddress (offset_addr);
7193 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7194 return false;
7195 }
7196
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007197 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007198 if (UnalignedSupport() || BitIsClear (address, 0))
7199 {
7200 // R[t] = SignExtend(data, 32);
7201 int64_t signed_data = llvm::SignExtend64<16>(data);
7202 context.type = eContextRegisterLoad;
7203 context.SetRegisterPlusOffset (base_reg, address - Rn);
7204 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7205 return false;
7206 }
7207 else // Can only apply before ARMv7
7208 {
7209 // R[t] = bits(32) UNKNOWN;
7210 WriteBits32Unknown (t);
7211 }
7212 }
7213 return true;
7214}
7215
Caroline Ticed2fac092011-03-02 19:45:34 +00007216// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7217// sign-extends it to from a 32-bit word, and writes it to a register.
7218bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007219EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007220{
7221#if 0
7222 if ConditionPassed() then
7223 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7224 base = Align(PC,4);
7225 address = if add then (base + imm32) else (base - imm32);
7226 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007227 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007228 R[t] = SignExtend(data, 32);
7229 else // Can only apply before ARMv7
7230 R[t] = bits(32) UNKNOWN;
7231#endif
7232
7233 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007234
Greg Clayton7bc39082011-03-24 23:53:38 +00007235 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007236 {
7237 uint32_t t;
7238 uint32_t imm32;
7239 bool add;
7240
7241 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7242 switch (encoding)
7243 {
7244 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007245 // if Rt == '1111' then SEE "Unallocated memory hints";
7246 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007247 t = Bits32 (opcode, 15, 12);
7248 imm32 = Bits32 (opcode, 11, 0);
7249 add = BitIsSet (opcode, 23);
7250
7251 // if t == 13 then UNPREDICTABLE;
7252 if (t == 13)
7253 return false;
7254
7255 break;
7256
7257 case eEncodingA1:
7258 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007259 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007260 t = Bits32 (opcode, 15, 12);
7261 uint32_t imm4H = Bits32 (opcode, 11, 8);
7262 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007263 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007264 add = BitIsSet (opcode, 23);
7265
7266 // if t == 15 then UNPREDICTABLE;
7267 if (t == 15)
7268 return false;
7269
7270 break;
7271 }
7272 default:
7273 return false;
7274 }
7275
7276 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007277 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007278 if (!success)
7279 return false;
7280
7281 uint64_t base = AlignPC (pc_value);
7282
7283 addr_t address;
7284 // address = if add then (base + imm32) else (base - imm32);
7285 if (add)
7286 address = base + imm32;
7287 else
7288 address = base - imm32;
7289
7290 // data = MemU[address,2];
7291 Register base_reg;
7292 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7293
7294 EmulateInstruction::Context context;
7295 context.type = eContextRegisterLoad;
7296 context.SetRegisterPlusOffset (base_reg, imm32);
7297
7298 uint64_t data = MemURead (context, address, 2, 0, &success);
7299 if (!success)
7300 return false;
7301
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007302 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007303 if (UnalignedSupport() || BitIsClear (address, 0))
7304 {
7305 // R[t] = SignExtend(data, 32);
7306 int64_t signed_data = llvm::SignExtend64<16>(data);
7307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7308 return false;
7309 }
7310 else // Can only apply before ARMv7
7311 {
7312 // R[t] = bits(32) UNKNOWN;
7313 WriteBits32Unknown (t);
7314 }
7315 }
7316 return true;
7317}
7318
Caroline Tice291a3e92011-03-02 21:13:44 +00007319// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7320// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7321// shifted left by 0, 1, 2, or 3 bits.
7322bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007323EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007324{
7325#if 0
7326 if ConditionPassed() then
7327 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7328 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7329 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7330 address = if index then offset_addr else R[n];
7331 data = MemU[address,2];
7332 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007333 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007334 R[t] = SignExtend(data, 32);
7335 else // Can only apply before ARMv7
7336 R[t] = bits(32) UNKNOWN;
7337#endif
7338
7339 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007340
Greg Clayton7bc39082011-03-24 23:53:38 +00007341 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007342 {
7343 uint32_t t;
7344 uint32_t n;
7345 uint32_t m;
7346 bool index;
7347 bool add;
7348 bool wback;
7349 ARM_ShifterType shift_t;
7350 uint32_t shift_n;
7351
7352 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7353 switch (encoding)
7354 {
7355 case eEncodingT1:
7356 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7357 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7358 t = Bits32 (opcode, 2, 0);
7359 n = Bits32 (opcode, 5, 3);
7360 m = Bits32 (opcode, 8, 6);
7361
7362 // index = TRUE; add = TRUE; wback = FALSE;
7363 index = true;
7364 add = true;
7365 wback = false;
7366
7367 // (shift_t, shift_n) = (SRType_LSL, 0);
7368 shift_t = SRType_LSL;
7369 shift_n = 0;
7370
7371 break;
7372
7373 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007374 // if Rn == '1111' then SEE LDRSH (literal);
7375 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007376 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7377 t = Bits32 (opcode, 15, 12);
7378 n = Bits32 (opcode, 19, 16);
7379 m = Bits32 (opcode, 3, 0);
7380
7381 // index = TRUE; add = TRUE; wback = FALSE;
7382 index = true;
7383 add = true;
7384 wback = false;
7385
7386 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7387 shift_t = SRType_LSL;
7388 shift_n = Bits32 (opcode, 5, 4);
7389
7390 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7391 if ((t == 13) || BadReg (m))
7392 return false;
7393
7394 break;
7395
7396 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007397 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007398 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7399 t = Bits32 (opcode, 15, 12);
7400 n = Bits32 (opcode, 19, 16);
7401 m = Bits32 (opcode, 3, 0);
7402
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007403 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007404 index = BitIsSet (opcode, 24);
7405 add = BitIsSet (opcode, 23);
7406 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7407
7408 // (shift_t, shift_n) = (SRType_LSL, 0);
7409 shift_t = SRType_LSL;
7410 shift_n = 0;
7411
7412 // if t == 15 || m == 15 then UNPREDICTABLE;
7413 if ((t == 15) || (m == 15))
7414 return false;
7415
7416 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7417 if (wback && ((n == 15) || (n == t)))
7418 return false;
7419
7420 break;
7421
7422 default:
7423 break;
7424 }
7425
7426 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7427 if (!success)
7428 return false;
7429
7430 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7431 if (!success)
7432 return false;
7433
7434 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7435 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7436
7437 addr_t offset_addr;
7438 addr_t address;
7439
7440 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7441 if (add)
7442 offset_addr = Rn + offset;
7443 else
7444 offset_addr = Rn - offset;
7445
7446 // address = if index then offset_addr else R[n];
7447 if (index)
7448 address = offset_addr;
7449 else
7450 address = Rn;
7451
7452 // data = MemU[address,2];
7453 Register base_reg;
7454 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7455
7456 Register offset_reg;
7457 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7458
7459 EmulateInstruction::Context context;
7460 context.type = eContextRegisterLoad;
7461 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7462
7463 uint64_t data = MemURead (context, address, 2, 0, &success);
7464 if (!success)
7465 return false;
7466
7467 // if wback then R[n] = offset_addr;
7468 if (wback)
7469 {
7470 context.type = eContextAdjustBaseRegister;
7471 context.SetAddress (offset_addr);
7472 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7473 return false;
7474 }
7475
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007476 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007477 if (UnalignedSupport() || BitIsClear (address, 0))
7478 {
7479 // R[t] = SignExtend(data, 32);
7480 context.type = eContextRegisterLoad;
7481 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7482
7483 int64_t signed_data = llvm::SignExtend64<16>(data);
7484 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7485 return false;
7486 }
7487 else // Can only apply before ARMv7
7488 {
7489 // R[t] = bits(32) UNKNOWN;
7490 WriteBits32Unknown (t);
7491 }
7492 }
7493 return true;
7494}
Caroline Tice6bf65162011-03-03 17:42:58 +00007495
7496// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7497// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7498bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007499EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007500{
7501#if 0
7502 if ConditionPassed() then
7503 EncodingSpecificOperations();
7504 rotated = ROR(R[m], rotation);
7505 R[d] = SignExtend(rotated<7:0>, 32);
7506#endif
7507
7508 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007509
Greg Clayton7bc39082011-03-24 23:53:38 +00007510 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007511 {
7512 uint32_t d;
7513 uint32_t m;
7514 uint32_t rotation;
7515
7516 // EncodingSpecificOperations();
7517 switch (encoding)
7518 {
7519 case eEncodingT1:
7520 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7521 d = Bits32 (opcode, 2, 0);
7522 m = Bits32 (opcode, 5, 3);
7523 rotation = 0;
7524
7525 break;
7526
7527 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007528 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007529 d = Bits32 (opcode, 11, 8);
7530 m = Bits32 (opcode, 3, 0);
7531 rotation = Bits32 (opcode, 5, 4) << 3;
7532
7533 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7534 if (BadReg (d) || BadReg (m))
7535 return false;
7536
7537 break;
7538
7539 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007540 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007541 d = Bits32 (opcode, 15, 12);
7542 m = Bits32 (opcode, 3, 0);
7543 rotation = Bits32 (opcode, 11, 10) << 3;
7544
7545 // if d == 15 || m == 15 then UNPREDICTABLE;
7546 if ((d == 15) || (m == 15))
7547 return false;
7548
7549 break;
7550
7551 default:
7552 return false;
7553 }
7554
Caroline Tice868198b2011-03-03 18:04:49 +00007555 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7556 if (!success)
7557 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007558
7559 // rotated = ROR(R[m], rotation);
7560 uint64_t rotated = ROR (Rm, rotation);
7561
7562 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007563 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007564
7565 Register source_reg;
7566 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7567
7568 EmulateInstruction::Context context;
7569 context.type = eContextRegisterLoad;
7570 context.SetRegister (source_reg);
7571
Caroline Tice8ce96d92011-03-03 18:27:17 +00007572 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007573 return false;
7574 }
7575 return true;
7576}
Caroline Tice291a3e92011-03-02 21:13:44 +00007577
Caroline Tice868198b2011-03-03 18:04:49 +00007578// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7579// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7580bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007581EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007582{
7583#if 0
7584 if ConditionPassed() then
7585 EncodingSpecificOperations();
7586 rotated = ROR(R[m], rotation);
7587 R[d] = SignExtend(rotated<15:0>, 32);
7588#endif
7589
7590 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007591
Greg Clayton7bc39082011-03-24 23:53:38 +00007592 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007593 {
7594 uint32_t d;
7595 uint32_t m;
7596 uint32_t rotation;
7597
7598 // EncodingSpecificOperations();
7599 switch (encoding)
7600 {
7601 case eEncodingT1:
7602 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7603 d = Bits32 (opcode, 2, 0);
7604 m = Bits32 (opcode, 5, 3);
7605 rotation = 0;
7606
7607 break;
7608
7609 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007610 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007611 d = Bits32 (opcode, 11, 8);
7612 m = Bits32 (opcode, 3, 0);
7613 rotation = Bits32 (opcode, 5, 4) << 3;
7614
7615 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7616 if (BadReg (d) || BadReg (m))
7617 return false;
7618
7619 break;
7620
7621 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007622 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007623 d = Bits32 (opcode, 15, 12);
7624 m = Bits32 (opcode, 3, 0);
7625 rotation = Bits32 (opcode, 11, 10) << 3;
7626
7627 // if d == 15 || m == 15 then UNPREDICTABLE;
7628 if ((d == 15) || (m == 15))
7629 return false;
7630
7631 break;
7632
7633 default:
7634 return false;
7635 }
7636
7637 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7638 if (!success)
7639 return false;
7640
7641 // rotated = ROR(R[m], rotation);
7642 uint64_t rotated = ROR (Rm, rotation);
7643
7644 // R[d] = SignExtend(rotated<15:0>, 32);
7645 Register source_reg;
7646 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7647
7648 EmulateInstruction::Context context;
7649 context.type = eContextRegisterLoad;
7650 context.SetRegister (source_reg);
7651
Caroline Tice8ce96d92011-03-03 18:27:17 +00007652 int64_t data = llvm::SignExtend64<16> (rotated);
7653 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007654 return false;
7655 }
7656
7657 return true;
7658}
7659
Caroline Tice8ce96d92011-03-03 18:27:17 +00007660// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7661// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7662bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007663EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007664{
7665#if 0
7666 if ConditionPassed() then
7667 EncodingSpecificOperations();
7668 rotated = ROR(R[m], rotation);
7669 R[d] = ZeroExtend(rotated<7:0>, 32);
7670#endif
7671
7672 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007673
Greg Clayton7bc39082011-03-24 23:53:38 +00007674 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007675 {
7676 uint32_t d;
7677 uint32_t m;
7678 uint32_t rotation;
7679
7680 // EncodingSpecificOperations();
7681 switch (encoding)
7682 {
7683 case eEncodingT1:
7684 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7685 d = Bits32 (opcode, 2, 0);
7686 m = Bits32 (opcode, 5, 3);
7687 rotation = 0;
7688
7689 break;
7690
7691 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007692 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007693 d = Bits32 (opcode, 11, 8);
7694 m = Bits32 (opcode, 3, 0);
7695 rotation = Bits32 (opcode, 5, 4) << 3;
7696
7697 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7698 if (BadReg (d) || BadReg (m))
7699 return false;
7700
7701 break;
7702
7703 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007704 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007705 d = Bits32 (opcode, 15, 12);
7706 m = Bits32 (opcode, 3, 0);
7707 rotation = Bits32 (opcode, 11, 10) << 3;
7708
7709 // if d == 15 || m == 15 then UNPREDICTABLE;
7710 if ((d == 15) || (m == 15))
7711 return false;
7712
7713 break;
7714
7715 default:
7716 return false;
7717 }
7718
7719 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7720 if (!success)
7721 return false;
7722
7723 // rotated = ROR(R[m], rotation);
7724 uint64_t rotated = ROR (Rm, rotation);
7725
7726 // R[d] = ZeroExtend(rotated<7:0>, 32);
7727 Register source_reg;
7728 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7729
7730 EmulateInstruction::Context context;
7731 context.type = eContextRegisterLoad;
7732 context.SetRegister (source_reg);
7733
7734 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7735 return false;
7736 }
7737 return true;
7738}
7739
Caroline Tice11555f22011-03-03 18:48:58 +00007740// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7741// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7742bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007743EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007744{
7745#if 0
7746 if ConditionPassed() then
7747 EncodingSpecificOperations();
7748 rotated = ROR(R[m], rotation);
7749 R[d] = ZeroExtend(rotated<15:0>, 32);
7750#endif
7751
7752 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007753
Greg Clayton7bc39082011-03-24 23:53:38 +00007754 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007755 {
7756 uint32_t d;
7757 uint32_t m;
7758 uint32_t rotation;
7759
7760 switch (encoding)
7761 {
7762 case eEncodingT1:
7763 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7764 d = Bits32 (opcode, 2, 0);
7765 m = Bits32 (opcode, 5, 3);
7766 rotation = 0;
7767
7768 break;
7769
7770 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007771 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007772 d = Bits32 (opcode, 11, 8);
7773 m = Bits32 (opcode, 3, 0);
7774 rotation = Bits32 (opcode, 5, 4) << 3;
7775
7776 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7777 if (BadReg (d) || BadReg (m))
7778 return false;
7779
7780 break;
7781
7782 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007783 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007784 d = Bits32 (opcode, 15, 12);
7785 m = Bits32 (opcode, 3, 0);
7786 rotation = Bits32 (opcode, 11, 10) << 3;
7787
7788 // if d == 15 || m == 15 then UNPREDICTABLE;
7789 if ((d == 15) || (m == 15))
7790 return false;
7791
7792 break;
7793
7794 default:
7795 return false;
7796 }
7797
7798 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7799 if (!success)
7800 return false;
7801
7802 // rotated = ROR(R[m], rotation);
7803 uint64_t rotated = ROR (Rm, rotation);
7804
7805 // R[d] = ZeroExtend(rotated<15:0>, 32);
7806 Register source_reg;
7807 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7808
7809 EmulateInstruction::Context context;
7810 context.type = eContextRegisterLoad;
7811 context.SetRegister (source_reg);
7812
7813 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7814 return false;
7815 }
7816 return true;
7817}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007818
7819// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7820// word respectively.
7821bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007822EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007823{
7824#if 0
7825 if ConditionPassed() then
7826 EncodingSpecificOperations();
7827 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7828 UNPREDICTABLE;
7829 else
7830 address = if increment then R[n] else R[n]-8;
7831 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007832 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007833 BranchWritePC(MemA[address,4]);
7834 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7835#endif
7836
7837 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007838
Greg Clayton7bc39082011-03-24 23:53:38 +00007839 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007840 {
7841 uint32_t n;
7842 bool wback;
7843 bool increment;
7844 bool wordhigher;
7845
7846 // EncodingSpecificOperations();
7847 switch (encoding)
7848 {
7849 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007850 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007851 n = Bits32 (opcode, 19, 16);
7852 wback = BitIsSet (opcode, 21);
7853 increment = false;
7854 wordhigher = false;
7855
7856 // if n == 15 then UNPREDICTABLE;
7857 if (n == 15)
7858 return false;
7859
7860 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7861 if (InITBlock() && !LastInITBlock())
7862 return false;
7863
7864 break;
7865
7866 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007867 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007868 n = Bits32 (opcode, 19, 16);
7869 wback = BitIsSet (opcode, 21);
7870 increment = true;
7871 wordhigher = false;
7872
7873 // if n == 15 then UNPREDICTABLE;
7874 if (n == 15)
7875 return false;
7876
7877 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7878 if (InITBlock() && !LastInITBlock())
7879 return false;
7880
7881 break;
7882
7883 case eEncodingA1:
7884 // n = UInt(Rn);
7885 n = Bits32 (opcode, 19, 16);
7886
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007887 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007888 wback = BitIsSet (opcode, 21);
7889 increment = BitIsSet (opcode, 23);
7890 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7891
7892 // if n == 15 then UNPREDICTABLE;
7893 if (n == 15)
7894 return false;
7895
7896 break;
7897
7898 default:
7899 return false;
7900 }
7901
7902 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7903 if (!CurrentModeIsPrivileged ())
7904 // UNPREDICTABLE;
7905 return false;
7906 else
7907 {
7908 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7909 if (!success)
7910 return false;
7911
7912 addr_t address;
7913 // address = if increment then R[n] else R[n]-8;
7914 if (increment)
7915 address = Rn;
7916 else
7917 address = Rn - 8;
7918
7919 // if wordhigher then address = address+4;
7920 if (wordhigher)
7921 address = address + 4;
7922
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007923 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007924 Register base_reg;
7925 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7926
7927 EmulateInstruction::Context context;
7928 context.type = eContextReturnFromException;
7929 context.SetRegisterPlusOffset (base_reg, address - Rn);
7930
7931 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7932 if (!success)
7933 return false;
7934
7935 CPSRWriteByInstr (data, 15, true);
7936
7937 // BranchWritePC(MemA[address,4]);
7938 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7939 if (!success)
7940 return false;
7941
7942 BranchWritePC (context, data2);
7943
7944 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7945 if (wback)
7946 {
7947 context.type = eContextAdjustBaseRegister;
7948 if (increment)
7949 {
7950 context.SetOffset (8);
7951 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7952 return false;
7953 }
7954 else
7955 {
7956 context.SetOffset (-8);
7957 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
7958 return false;
7959 }
7960 } // if wback
7961 }
7962 } // if ConditionPassed()
7963 return true;
7964}
Caroline Tice11555f22011-03-03 18:48:58 +00007965
Johnny Chen2115b412011-02-21 23:42:44 +00007966// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7967// and writes the result to the destination register. It can optionally update the condition flags based on
7968// the result.
7969bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007970EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00007971{
7972#if 0
7973 // ARM pseudo code...
7974 if ConditionPassed() then
7975 EncodingSpecificOperations();
7976 result = R[n] EOR imm32;
7977 if d == 15 then // Can only occur for ARM encoding
7978 ALUWritePC(result); // setflags is always FALSE here
7979 else
7980 R[d] = result;
7981 if setflags then
7982 APSR.N = result<31>;
7983 APSR.Z = IsZeroBit(result);
7984 APSR.C = carry;
7985 // APSR.V unchanged
7986#endif
7987
7988 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00007989
Greg Clayton7bc39082011-03-24 23:53:38 +00007990 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00007991 {
7992 uint32_t Rd, Rn;
7993 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7994 bool setflags;
7995 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7996 switch (encoding)
7997 {
7998 case eEncodingT1:
7999 Rd = Bits32(opcode, 11, 8);
8000 Rn = Bits32(opcode, 19, 16);
8001 setflags = BitIsSet(opcode, 20);
8002 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8003 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8004 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008005 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008006 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8007 return false;
8008 break;
8009 case eEncodingA1:
8010 Rd = Bits32(opcode, 15, 12);
8011 Rn = Bits32(opcode, 19, 16);
8012 setflags = BitIsSet(opcode, 20);
8013 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8014 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8015 // TODO: Emulate SUBS PC, LR and related instructions.
8016 if (Rd == 15 && setflags)
8017 return false;
8018 break;
8019 default:
8020 return false;
8021 }
8022
8023 // Read the first operand.
8024 uint32_t val1 = ReadCoreReg(Rn, &success);
8025 if (!success)
8026 return false;
8027
8028 uint32_t result = val1 ^ imm32;
8029
8030 EmulateInstruction::Context context;
8031 context.type = EmulateInstruction::eContextImmediate;
8032 context.SetNoArgs ();
8033
8034 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8035 return false;
8036 }
8037 return true;
8038}
8039
8040// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8041// optionally-shifted register value, and writes the result to the destination register.
8042// It can optionally update the condition flags based on the result.
8043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008044EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008045{
8046#if 0
8047 // ARM pseudo code...
8048 if ConditionPassed() then
8049 EncodingSpecificOperations();
8050 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8051 result = R[n] EOR shifted;
8052 if d == 15 then // Can only occur for ARM encoding
8053 ALUWritePC(result); // setflags is always FALSE here
8054 else
8055 R[d] = result;
8056 if setflags then
8057 APSR.N = result<31>;
8058 APSR.Z = IsZeroBit(result);
8059 APSR.C = carry;
8060 // APSR.V unchanged
8061#endif
8062
8063 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008064
Greg Clayton7bc39082011-03-24 23:53:38 +00008065 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008066 {
8067 uint32_t Rd, Rn, Rm;
8068 ARM_ShifterType shift_t;
8069 uint32_t shift_n; // the shift applied to the value read from Rm
8070 bool setflags;
8071 uint32_t carry;
8072 switch (encoding)
8073 {
8074 case eEncodingT1:
8075 Rd = Rn = Bits32(opcode, 2, 0);
8076 Rm = Bits32(opcode, 5, 3);
8077 setflags = !InITBlock();
8078 shift_t = SRType_LSL;
8079 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008080 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008081 case eEncodingT2:
8082 Rd = Bits32(opcode, 11, 8);
8083 Rn = Bits32(opcode, 19, 16);
8084 Rm = Bits32(opcode, 3, 0);
8085 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008086 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8087 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008088 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008089 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008090 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8091 return false;
8092 break;
8093 case eEncodingA1:
8094 Rd = Bits32(opcode, 15, 12);
8095 Rn = Bits32(opcode, 19, 16);
8096 Rm = Bits32(opcode, 3, 0);
8097 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008098 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008099 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8100 // TODO: Emulate SUBS PC, LR and related instructions.
8101 if (Rd == 15 && setflags)
8102 return false;
8103 break;
8104 default:
8105 return false;
8106 }
8107
8108 // Read the first operand.
8109 uint32_t val1 = ReadCoreReg(Rn, &success);
8110 if (!success)
8111 return false;
8112
8113 // Read the second operand.
8114 uint32_t val2 = ReadCoreReg(Rm, &success);
8115 if (!success)
8116 return false;
8117
8118 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8119 uint32_t result = val1 ^ shifted;
8120
8121 EmulateInstruction::Context context;
8122 context.type = EmulateInstruction::eContextImmediate;
8123 context.SetNoArgs ();
8124
8125 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8126 return false;
8127 }
8128 return true;
8129}
8130
Johnny Chen7c5234d2011-02-18 23:41:11 +00008131// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8132// writes the result to the destination register. It can optionally update the condition flags based
8133// on the result.
8134bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008135EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008136{
8137#if 0
8138 // ARM pseudo code...
8139 if ConditionPassed() then
8140 EncodingSpecificOperations();
8141 result = R[n] OR imm32;
8142 if d == 15 then // Can only occur for ARM encoding
8143 ALUWritePC(result); // setflags is always FALSE here
8144 else
8145 R[d] = result;
8146 if setflags then
8147 APSR.N = result<31>;
8148 APSR.Z = IsZeroBit(result);
8149 APSR.C = carry;
8150 // APSR.V unchanged
8151#endif
8152
8153 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008154
Greg Clayton7bc39082011-03-24 23:53:38 +00008155 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008156 {
8157 uint32_t Rd, Rn;
8158 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8159 bool setflags;
8160 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8161 switch (encoding)
8162 {
8163 case eEncodingT1:
8164 Rd = Bits32(opcode, 11, 8);
8165 Rn = Bits32(opcode, 19, 16);
8166 setflags = BitIsSet(opcode, 20);
8167 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008168 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008169 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008170 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008171 if (BadReg(Rd) || Rn == 13)
8172 return false;
8173 break;
8174 case eEncodingA1:
8175 Rd = Bits32(opcode, 15, 12);
8176 Rn = Bits32(opcode, 19, 16);
8177 setflags = BitIsSet(opcode, 20);
8178 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8179 // TODO: Emulate SUBS PC, LR and related instructions.
8180 if (Rd == 15 && setflags)
8181 return false;
8182 break;
8183 default:
8184 return false;
8185 }
8186
8187 // Read the first operand.
8188 uint32_t val1 = ReadCoreReg(Rn, &success);
8189 if (!success)
8190 return false;
8191
8192 uint32_t result = val1 | imm32;
8193
8194 EmulateInstruction::Context context;
8195 context.type = EmulateInstruction::eContextImmediate;
8196 context.SetNoArgs ();
8197
8198 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8199 return false;
8200 }
8201 return true;
8202}
8203
8204// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8205// value, and writes the result to the destination register. It can optionally update the condition flags based
8206// on the result.
8207bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008208EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008209{
8210#if 0
8211 // ARM pseudo code...
8212 if ConditionPassed() then
8213 EncodingSpecificOperations();
8214 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8215 result = R[n] OR shifted;
8216 if d == 15 then // Can only occur for ARM encoding
8217 ALUWritePC(result); // setflags is always FALSE here
8218 else
8219 R[d] = result;
8220 if setflags then
8221 APSR.N = result<31>;
8222 APSR.Z = IsZeroBit(result);
8223 APSR.C = carry;
8224 // APSR.V unchanged
8225#endif
8226
8227 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008228
Greg Clayton7bc39082011-03-24 23:53:38 +00008229 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008230 {
8231 uint32_t Rd, Rn, Rm;
8232 ARM_ShifterType shift_t;
8233 uint32_t shift_n; // the shift applied to the value read from Rm
8234 bool setflags;
8235 uint32_t carry;
8236 switch (encoding)
8237 {
8238 case eEncodingT1:
8239 Rd = Rn = Bits32(opcode, 2, 0);
8240 Rm = Bits32(opcode, 5, 3);
8241 setflags = !InITBlock();
8242 shift_t = SRType_LSL;
8243 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008244 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008245 case eEncodingT2:
8246 Rd = Bits32(opcode, 11, 8);
8247 Rn = Bits32(opcode, 19, 16);
8248 Rm = Bits32(opcode, 3, 0);
8249 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008250 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8251 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008252 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008253 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008254 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8255 return false;
8256 break;
8257 case eEncodingA1:
8258 Rd = Bits32(opcode, 15, 12);
8259 Rn = Bits32(opcode, 19, 16);
8260 Rm = Bits32(opcode, 3, 0);
8261 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008262 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008263 // TODO: Emulate SUBS PC, LR and related instructions.
8264 if (Rd == 15 && setflags)
8265 return false;
8266 break;
8267 default:
8268 return false;
8269 }
8270
8271 // Read the first operand.
8272 uint32_t val1 = ReadCoreReg(Rn, &success);
8273 if (!success)
8274 return false;
8275
8276 // Read the second operand.
8277 uint32_t val2 = ReadCoreReg(Rm, &success);
8278 if (!success)
8279 return false;
8280
8281 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008282 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008283
8284 EmulateInstruction::Context context;
8285 context.type = EmulateInstruction::eContextImmediate;
8286 context.SetNoArgs ();
8287
8288 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8289 return false;
8290 }
8291 return true;
8292}
8293
Johnny Chened32e7c2011-02-22 23:42:58 +00008294// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8295// the destination register. It can optionally update the condition flags based on the result.
8296bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008297EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008298{
8299#if 0
8300 // ARM pseudo code...
8301 if ConditionPassed() then
8302 EncodingSpecificOperations();
8303 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8304 if d == 15 then // Can only occur for ARM encoding
8305 ALUWritePC(result); // setflags is always FALSE here
8306 else
8307 R[d] = result;
8308 if setflags then
8309 APSR.N = result<31>;
8310 APSR.Z = IsZeroBit(result);
8311 APSR.C = carry;
8312 APSR.V = overflow;
8313#endif
8314
8315 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008316
8317 uint32_t Rd; // the destination register
8318 uint32_t Rn; // the first operand
8319 bool setflags;
8320 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8321 switch (encoding) {
8322 case eEncodingT1:
8323 Rd = Bits32(opcode, 2, 0);
8324 Rn = Bits32(opcode, 5, 3);
8325 setflags = !InITBlock();
8326 imm32 = 0;
8327 break;
8328 case eEncodingT2:
8329 Rd = Bits32(opcode, 11, 8);
8330 Rn = Bits32(opcode, 19, 16);
8331 setflags = BitIsSet(opcode, 20);
8332 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8333 if (BadReg(Rd) || BadReg(Rn))
8334 return false;
8335 break;
8336 case eEncodingA1:
8337 Rd = Bits32(opcode, 15, 12);
8338 Rn = Bits32(opcode, 19, 16);
8339 setflags = BitIsSet(opcode, 20);
8340 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8341 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8342 // TODO: Emulate SUBS PC, LR and related instructions.
8343 if (Rd == 15 && setflags)
8344 return false;
8345 break;
8346 default:
8347 return false;
8348 }
8349 // Read the register value from the operand register Rn.
8350 uint32_t reg_val = ReadCoreReg(Rn, &success);
8351 if (!success)
8352 return false;
8353
8354 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8355
8356 EmulateInstruction::Context context;
8357 context.type = EmulateInstruction::eContextImmediate;
8358 context.SetNoArgs ();
8359
8360 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8361 return false;
8362
8363 return true;
8364}
8365
8366// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8367// result to the destination register. It can optionally update the condition flags based on the result.
8368bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008369EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008370{
8371#if 0
8372 // ARM pseudo code...
8373 if ConditionPassed() then
8374 EncodingSpecificOperations();
8375 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8376 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8377 if d == 15 then // Can only occur for ARM encoding
8378 ALUWritePC(result); // setflags is always FALSE here
8379 else
8380 R[d] = result;
8381 if setflags then
8382 APSR.N = result<31>;
8383 APSR.Z = IsZeroBit(result);
8384 APSR.C = carry;
8385 APSR.V = overflow;
8386#endif
8387
8388 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008389
8390 uint32_t Rd; // the destination register
8391 uint32_t Rn; // the first operand
8392 uint32_t Rm; // the second operand
8393 bool setflags;
8394 ARM_ShifterType shift_t;
8395 uint32_t shift_n; // the shift applied to the value read from Rm
8396 switch (encoding) {
8397 case eEncodingT1:
8398 Rd = Bits32(opcode, 11, 8);
8399 Rn = Bits32(opcode, 19, 16);
8400 Rm = Bits32(opcode, 3, 0);
8401 setflags = BitIsSet(opcode, 20);
8402 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8403 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8404 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8405 return false;
8406 break;
8407 case eEncodingA1:
8408 Rd = Bits32(opcode, 15, 12);
8409 Rn = Bits32(opcode, 19, 16);
8410 Rm = Bits32(opcode, 3, 0);
8411 setflags = BitIsSet(opcode, 20);
8412 shift_n = DecodeImmShiftARM(opcode, shift_t);
8413 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8414 // TODO: Emulate SUBS PC, LR and related instructions.
8415 if (Rd == 15 && setflags)
8416 return false;
8417 break;
8418 default:
8419 return false;
8420 }
8421 // Read the register value from register Rn.
8422 uint32_t val1 = ReadCoreReg(Rn, &success);
8423 if (!success)
8424 return false;
8425
8426 // Read the register value from register Rm.
8427 uint32_t val2 = ReadCoreReg(Rm, &success);
8428 if (!success)
8429 return false;
8430
8431 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8432 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8433
8434 EmulateInstruction::Context context;
8435 context.type = EmulateInstruction::eContextImmediate;
8436 context.SetNoArgs();
8437 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8438 return false;
8439
8440 return true;
8441}
8442
Johnny Chen90e607b2011-02-23 00:07:09 +00008443// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8444// an immediate value, and writes the result to the destination register. It can optionally update the condition
8445// flags based on the result.
8446bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008447EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008448{
8449#if 0
8450 // ARM pseudo code...
8451 if ConditionPassed() then
8452 EncodingSpecificOperations();
8453 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8454 if d == 15 then
8455 ALUWritePC(result); // setflags is always FALSE here
8456 else
8457 R[d] = result;
8458 if setflags then
8459 APSR.N = result<31>;
8460 APSR.Z = IsZeroBit(result);
8461 APSR.C = carry;
8462 APSR.V = overflow;
8463#endif
8464
8465 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008466
8467 uint32_t Rd; // the destination register
8468 uint32_t Rn; // the first operand
8469 bool setflags;
8470 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8471 switch (encoding) {
8472 case eEncodingA1:
8473 Rd = Bits32(opcode, 15, 12);
8474 Rn = Bits32(opcode, 19, 16);
8475 setflags = BitIsSet(opcode, 20);
8476 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8477 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8478 // TODO: Emulate SUBS PC, LR and related instructions.
8479 if (Rd == 15 && setflags)
8480 return false;
8481 break;
8482 default:
8483 return false;
8484 }
8485 // Read the register value from the operand register Rn.
8486 uint32_t reg_val = ReadCoreReg(Rn, &success);
8487 if (!success)
8488 return false;
8489
8490 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8491
8492 EmulateInstruction::Context context;
8493 context.type = EmulateInstruction::eContextImmediate;
8494 context.SetNoArgs ();
8495
8496 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8497 return false;
8498
8499 return true;
8500}
8501
8502// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8503// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8504// condition flags based on the result.
8505bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008506EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008507{
8508#if 0
8509 // ARM pseudo code...
8510 if ConditionPassed() then
8511 EncodingSpecificOperations();
8512 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8513 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8514 if d == 15 then
8515 ALUWritePC(result); // setflags is always FALSE here
8516 else
8517 R[d] = result;
8518 if setflags then
8519 APSR.N = result<31>;
8520 APSR.Z = IsZeroBit(result);
8521 APSR.C = carry;
8522 APSR.V = overflow;
8523#endif
8524
8525 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008526
8527 uint32_t Rd; // the destination register
8528 uint32_t Rn; // the first operand
8529 uint32_t Rm; // the second operand
8530 bool setflags;
8531 ARM_ShifterType shift_t;
8532 uint32_t shift_n; // the shift applied to the value read from Rm
8533 switch (encoding) {
8534 case eEncodingA1:
8535 Rd = Bits32(opcode, 15, 12);
8536 Rn = Bits32(opcode, 19, 16);
8537 Rm = Bits32(opcode, 3, 0);
8538 setflags = BitIsSet(opcode, 20);
8539 shift_n = DecodeImmShiftARM(opcode, shift_t);
8540 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8541 // TODO: Emulate SUBS PC, LR and related instructions.
8542 if (Rd == 15 && setflags)
8543 return false;
8544 break;
8545 default:
8546 return false;
8547 }
8548 // Read the register value from register Rn.
8549 uint32_t val1 = ReadCoreReg(Rn, &success);
8550 if (!success)
8551 return false;
8552
8553 // Read the register value from register Rm.
8554 uint32_t val2 = ReadCoreReg(Rm, &success);
8555 if (!success)
8556 return false;
8557
8558 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8559 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8560
8561 EmulateInstruction::Context context;
8562 context.type = EmulateInstruction::eContextImmediate;
8563 context.SetNoArgs();
8564 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8565 return false;
8566
8567 return true;
8568}
8569
Johnny Chen9b381772011-02-23 01:01:21 +00008570// Subtract with Carry (immediate) subtracts an immediate value and the value of
8571// NOT (Carry flag) from a register value, and writes the result to the destination register.
8572// It can optionally update the condition flags based on the result.
8573bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008574EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008575{
8576#if 0
8577 // ARM pseudo code...
8578 if ConditionPassed() then
8579 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008580 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008581 if d == 15 then // Can only occur for ARM encoding
8582 ALUWritePC(result); // setflags is always FALSE here
8583 else
8584 R[d] = result;
8585 if setflags then
8586 APSR.N = result<31>;
8587 APSR.Z = IsZeroBit(result);
8588 APSR.C = carry;
8589 APSR.V = overflow;
8590#endif
8591
8592 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008593
8594 uint32_t Rd; // the destination register
8595 uint32_t Rn; // the first operand
8596 bool setflags;
8597 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8598 switch (encoding) {
8599 case eEncodingT1:
8600 Rd = Bits32(opcode, 11, 8);
8601 Rn = Bits32(opcode, 19, 16);
8602 setflags = BitIsSet(opcode, 20);
8603 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8604 if (BadReg(Rd) || BadReg(Rn))
8605 return false;
8606 break;
8607 case eEncodingA1:
8608 Rd = Bits32(opcode, 15, 12);
8609 Rn = Bits32(opcode, 19, 16);
8610 setflags = BitIsSet(opcode, 20);
8611 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8612 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8613 // TODO: Emulate SUBS PC, LR and related instructions.
8614 if (Rd == 15 && setflags)
8615 return false;
8616 break;
8617 default:
8618 return false;
8619 }
8620 // Read the register value from the operand register Rn.
8621 uint32_t reg_val = ReadCoreReg(Rn, &success);
8622 if (!success)
8623 return false;
8624
8625 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8626
8627 EmulateInstruction::Context context;
8628 context.type = EmulateInstruction::eContextImmediate;
8629 context.SetNoArgs ();
8630
8631 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8632 return false;
8633
8634 return true;
8635}
8636
8637// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8638// NOT (Carry flag) from a register value, and writes the result to the destination register.
8639// It can optionally update the condition flags based on the result.
8640bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008641EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008642{
8643#if 0
8644 // ARM pseudo code...
8645 if ConditionPassed() then
8646 EncodingSpecificOperations();
8647 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8648 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8649 if d == 15 then // Can only occur for ARM encoding
8650 ALUWritePC(result); // setflags is always FALSE here
8651 else
8652 R[d] = result;
8653 if setflags then
8654 APSR.N = result<31>;
8655 APSR.Z = IsZeroBit(result);
8656 APSR.C = carry;
8657 APSR.V = overflow;
8658#endif
8659
8660 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008661
8662 uint32_t Rd; // the destination register
8663 uint32_t Rn; // the first operand
8664 uint32_t Rm; // the second operand
8665 bool setflags;
8666 ARM_ShifterType shift_t;
8667 uint32_t shift_n; // the shift applied to the value read from Rm
8668 switch (encoding) {
8669 case eEncodingT1:
8670 Rd = Rn = Bits32(opcode, 2, 0);
8671 Rm = Bits32(opcode, 5, 3);
8672 setflags = !InITBlock();
8673 shift_t = SRType_LSL;
8674 shift_n = 0;
8675 break;
8676 case eEncodingT2:
8677 Rd = Bits32(opcode, 11, 8);
8678 Rn = Bits32(opcode, 19, 16);
8679 Rm = Bits32(opcode, 3, 0);
8680 setflags = BitIsSet(opcode, 20);
8681 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8682 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8683 return false;
8684 break;
8685 case eEncodingA1:
8686 Rd = Bits32(opcode, 15, 12);
8687 Rn = Bits32(opcode, 19, 16);
8688 Rm = Bits32(opcode, 3, 0);
8689 setflags = BitIsSet(opcode, 20);
8690 shift_n = DecodeImmShiftARM(opcode, shift_t);
8691 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8692 // TODO: Emulate SUBS PC, LR and related instructions.
8693 if (Rd == 15 && setflags)
8694 return false;
8695 break;
8696 default:
8697 return false;
8698 }
8699 // Read the register value from register Rn.
8700 uint32_t val1 = ReadCoreReg(Rn, &success);
8701 if (!success)
8702 return false;
8703
8704 // Read the register value from register Rm.
8705 uint32_t val2 = ReadCoreReg(Rm, &success);
8706 if (!success)
8707 return false;
8708
8709 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8710 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8711
8712 EmulateInstruction::Context context;
8713 context.type = EmulateInstruction::eContextImmediate;
8714 context.SetNoArgs();
8715 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8716 return false;
8717
8718 return true;
8719}
8720
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008721// This instruction subtracts an immediate value from a register value, and writes the result
8722// to the destination register. It can optionally update the condition flags based on the result.
8723bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008724EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008725{
8726#if 0
8727 // ARM pseudo code...
8728 if ConditionPassed() then
8729 EncodingSpecificOperations();
8730 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8731 R[d] = result;
8732 if setflags then
8733 APSR.N = result<31>;
8734 APSR.Z = IsZeroBit(result);
8735 APSR.C = carry;
8736 APSR.V = overflow;
8737#endif
8738
8739 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008740
8741 uint32_t Rd; // the destination register
8742 uint32_t Rn; // the first operand
8743 bool setflags;
8744 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8745 switch (encoding) {
8746 case eEncodingT1:
8747 Rd = Bits32(opcode, 2, 0);
8748 Rn = Bits32(opcode, 5, 3);
8749 setflags = !InITBlock();
8750 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8751 break;
8752 case eEncodingT2:
8753 Rd = Rn = Bits32(opcode, 10, 8);
8754 setflags = !InITBlock();
8755 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8756 break;
8757 case eEncodingT3:
8758 Rd = Bits32(opcode, 11, 8);
8759 Rn = Bits32(opcode, 19, 16);
8760 setflags = BitIsSet(opcode, 20);
8761 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8762
8763 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8764 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008765 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008766
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008767 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008768 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008769 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008770
8771 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8772 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8773 return false;
8774 break;
8775 case eEncodingT4:
8776 Rd = Bits32(opcode, 11, 8);
8777 Rn = Bits32(opcode, 19, 16);
8778 setflags = BitIsSet(opcode, 20);
8779 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8780
8781 // if Rn == '1111' then SEE ADR;
8782 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008783 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008784
8785 // if Rn == '1101' then SEE SUB (SP minus immediate);
8786 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008787 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008788
8789 if (BadReg(Rd))
8790 return false;
8791 break;
8792 default:
8793 return false;
8794 }
8795 // Read the register value from the operand register Rn.
8796 uint32_t reg_val = ReadCoreReg(Rn, &success);
8797 if (!success)
8798 return false;
8799
8800 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8801
8802 EmulateInstruction::Context context;
8803 context.type = EmulateInstruction::eContextImmediate;
8804 context.SetNoArgs ();
8805
8806 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8807 return false;
8808
8809 return true;
8810}
8811
8812// This instruction subtracts an immediate value from a register value, and writes the result
8813// to the destination register. It can optionally update the condition flags based on the result.
8814bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008815EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008816{
8817#if 0
8818 // ARM pseudo code...
8819 if ConditionPassed() then
8820 EncodingSpecificOperations();
8821 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8822 if d == 15 then
8823 ALUWritePC(result); // setflags is always FALSE here
8824 else
8825 R[d] = result;
8826 if setflags then
8827 APSR.N = result<31>;
8828 APSR.Z = IsZeroBit(result);
8829 APSR.C = carry;
8830 APSR.V = overflow;
8831#endif
8832
8833 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008834
8835 uint32_t Rd; // the destination register
8836 uint32_t Rn; // the first operand
8837 bool setflags;
8838 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8839 switch (encoding) {
8840 case eEncodingA1:
8841 Rd = Bits32(opcode, 15, 12);
8842 Rn = Bits32(opcode, 19, 16);
8843 setflags = BitIsSet(opcode, 20);
8844 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8845
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008846 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008847 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008848 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008849
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008850 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008851 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008852 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008853
8854 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8855 // TODO: Emulate SUBS PC, LR and related instructions.
8856 if (Rd == 15 && setflags)
8857 return false;
8858 break;
8859 default:
8860 return false;
8861 }
8862 // Read the register value from the operand register Rn.
8863 uint32_t reg_val = ReadCoreReg(Rn, &success);
8864 if (!success)
8865 return false;
8866
8867 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8868
8869 EmulateInstruction::Context context;
8870 context.type = EmulateInstruction::eContextImmediate;
8871 context.SetNoArgs ();
8872
8873 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8874 return false;
8875
8876 return true;
8877}
8878
Johnny Chen2115b412011-02-21 23:42:44 +00008879// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8880// immediate value. It updates the condition flags based on the result, and discards the result.
8881bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008882EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008883{
8884#if 0
8885 // ARM pseudo code...
8886 if ConditionPassed() then
8887 EncodingSpecificOperations();
8888 result = R[n] EOR imm32;
8889 APSR.N = result<31>;
8890 APSR.Z = IsZeroBit(result);
8891 APSR.C = carry;
8892 // APSR.V unchanged
8893#endif
8894
8895 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008896
Greg Clayton7bc39082011-03-24 23:53:38 +00008897 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008898 {
8899 uint32_t Rn;
8900 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8901 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8902 switch (encoding)
8903 {
8904 case eEncodingT1:
8905 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008906 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008907 if (BadReg(Rn))
8908 return false;
8909 break;
8910 case eEncodingA1:
8911 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008912 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008913 break;
8914 default:
8915 return false;
8916 }
8917
8918 // Read the first operand.
8919 uint32_t val1 = ReadCoreReg(Rn, &success);
8920 if (!success)
8921 return false;
8922
8923 uint32_t result = val1 ^ imm32;
8924
8925 EmulateInstruction::Context context;
8926 context.type = EmulateInstruction::eContextImmediate;
8927 context.SetNoArgs ();
8928
8929 if (!WriteFlags(context, result, carry))
8930 return false;
8931 }
8932 return true;
8933}
8934
8935// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8936// optionally-shifted register value. It updates the condition flags based on the result, and discards
8937// the result.
8938bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008939EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008940{
8941#if 0
8942 // ARM pseudo code...
8943 if ConditionPassed() then
8944 EncodingSpecificOperations();
8945 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8946 result = R[n] EOR shifted;
8947 APSR.N = result<31>;
8948 APSR.Z = IsZeroBit(result);
8949 APSR.C = carry;
8950 // APSR.V unchanged
8951#endif
8952
8953 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008954
Greg Clayton7bc39082011-03-24 23:53:38 +00008955 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008956 {
8957 uint32_t Rn, Rm;
8958 ARM_ShifterType shift_t;
8959 uint32_t shift_n; // the shift applied to the value read from Rm
8960 uint32_t carry;
8961 switch (encoding)
8962 {
8963 case eEncodingT1:
8964 Rn = Bits32(opcode, 19, 16);
8965 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008966 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008967 if (BadReg(Rn) || BadReg(Rm))
8968 return false;
8969 break;
8970 case eEncodingA1:
8971 Rn = Bits32(opcode, 19, 16);
8972 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008973 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008974 break;
8975 default:
8976 return false;
8977 }
8978
8979 // Read the first operand.
8980 uint32_t val1 = ReadCoreReg(Rn, &success);
8981 if (!success)
8982 return false;
8983
8984 // Read the second operand.
8985 uint32_t val2 = ReadCoreReg(Rm, &success);
8986 if (!success)
8987 return false;
8988
8989 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8990 uint32_t result = val1 ^ shifted;
8991
8992 EmulateInstruction::Context context;
8993 context.type = EmulateInstruction::eContextImmediate;
8994 context.SetNoArgs ();
8995
8996 if (!WriteFlags(context, result, carry))
8997 return false;
8998 }
8999 return true;
9000}
9001
Johnny Chende3cce32011-02-21 21:24:49 +00009002// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9003// It updates the condition flags based on the result, and discards the result.
9004bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009005EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009006{
9007#if 0
9008 // ARM pseudo code...
9009 if ConditionPassed() then
9010 EncodingSpecificOperations();
9011 result = R[n] AND imm32;
9012 APSR.N = result<31>;
9013 APSR.Z = IsZeroBit(result);
9014 APSR.C = carry;
9015 // APSR.V unchanged
9016#endif
9017
9018 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009019
Greg Clayton7bc39082011-03-24 23:53:38 +00009020 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009021 {
9022 uint32_t Rn;
9023 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9024 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9025 switch (encoding)
9026 {
9027 case eEncodingT1:
9028 Rn = Bits32(opcode, 19, 16);
9029 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9030 if (BadReg(Rn))
9031 return false;
9032 break;
9033 case eEncodingA1:
9034 Rn = Bits32(opcode, 19, 16);
9035 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9036 break;
9037 default:
9038 return false;
9039 }
9040
9041 // Read the first operand.
9042 uint32_t val1 = ReadCoreReg(Rn, &success);
9043 if (!success)
9044 return false;
9045
9046 uint32_t result = val1 & imm32;
9047
9048 EmulateInstruction::Context context;
9049 context.type = EmulateInstruction::eContextImmediate;
9050 context.SetNoArgs ();
9051
9052 if (!WriteFlags(context, result, carry))
9053 return false;
9054 }
9055 return true;
9056}
9057
9058// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9059// It updates the condition flags based on the result, and discards the result.
9060bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009061EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009062{
9063#if 0
9064 // ARM pseudo code...
9065 if ConditionPassed() then
9066 EncodingSpecificOperations();
9067 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9068 result = R[n] AND shifted;
9069 APSR.N = result<31>;
9070 APSR.Z = IsZeroBit(result);
9071 APSR.C = carry;
9072 // APSR.V unchanged
9073#endif
9074
9075 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009076
Greg Clayton7bc39082011-03-24 23:53:38 +00009077 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009078 {
9079 uint32_t Rn, Rm;
9080 ARM_ShifterType shift_t;
9081 uint32_t shift_n; // the shift applied to the value read from Rm
9082 uint32_t carry;
9083 switch (encoding)
9084 {
9085 case eEncodingT1:
9086 Rn = Bits32(opcode, 2, 0);
9087 Rm = Bits32(opcode, 5, 3);
9088 shift_t = SRType_LSL;
9089 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009090 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009091 case eEncodingT2:
9092 Rn = Bits32(opcode, 19, 16);
9093 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009094 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009095 if (BadReg(Rn) || BadReg(Rm))
9096 return false;
9097 break;
9098 case eEncodingA1:
9099 Rn = Bits32(opcode, 19, 16);
9100 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009101 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009102 break;
9103 default:
9104 return false;
9105 }
9106
9107 // Read the first operand.
9108 uint32_t val1 = ReadCoreReg(Rn, &success);
9109 if (!success)
9110 return false;
9111
9112 // Read the second operand.
9113 uint32_t val2 = ReadCoreReg(Rm, &success);
9114 if (!success)
9115 return false;
9116
9117 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9118 uint32_t result = val1 & shifted;
9119
9120 EmulateInstruction::Context context;
9121 context.type = EmulateInstruction::eContextImmediate;
9122 context.SetNoArgs ();
9123
9124 if (!WriteFlags(context, result, carry))
9125 return false;
9126 }
9127 return true;
9128}
9129
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009130EmulateInstructionARM::ARMOpcode*
9131EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009132{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009133 static ARMOpcode
9134 g_arm_opcodes[] =
9135 {
9136 //----------------------------------------------------------------------
9137 // Prologue instructions
9138 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009139
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009140 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009141 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9142 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009144 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009145 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009146 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009147 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009148 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9149 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009150 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009151
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009152 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009153 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009154
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009155 // push one register
9156 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009157 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009158
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009159 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009160 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9161 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009162
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009163 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009164 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009165 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009166
Johnny Chen9f687722011-02-18 00:02:28 +00009167 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9168 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009169 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009170 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9171
9172 //----------------------------------------------------------------------
9173 // Supervisor Call (previously Software Interrupt)
9174 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009175 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9176
9177 //----------------------------------------------------------------------
9178 // Branch instructions
9179 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009180 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009181 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9182 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9183 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9184 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009185 // for example, "bx lr"
9186 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009187 // bxj
9188 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009189
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009190 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009191 // Data-processing instructions
9192 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009193 // adc (immediate)
9194 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9195 // adc (register)
9196 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009197 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009198 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009199 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009200 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009201 // adr
9202 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9203 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009204 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009205 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009206 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009207 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009208 // bic (immediate)
9209 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9210 // bic (register)
9211 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009212 // eor (immediate)
9213 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9214 // eor (register)
9215 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009216 // orr (immediate)
9217 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9218 // orr (register)
9219 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009220 // rsb (immediate)
9221 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9222 // rsb (register)
9223 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009224 // rsc (immediate)
9225 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9226 // rsc (register)
9227 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009228 // sbc (immediate)
9229 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9230 // sbc (register)
9231 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009232 // sub (immediate, ARM)
9233 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009234 // sub (sp minus immediate)
9235 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009236 // teq (immediate)
9237 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9238 // teq (register)
9239 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009240 // tst (immediate)
9241 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9242 // tst (register)
9243 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9244
9245
Johnny Chen01d61572011-02-25 00:23:25 +00009246 // mov (register)
9247 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009248 // mvn (immediate)
9249 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9250 // mvn (register)
9251 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009252 // cmn (immediate)
9253 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9254 // cmn (register)
9255 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009256 // cmp (immediate)
9257 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9258 // cmp (register)
9259 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009260 // asr (immediate)
9261 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009262 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009263 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009264 // lsl (immediate)
9265 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9266 // lsl (register)
9267 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9268 // lsr (immediate)
9269 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9270 // lsr (register)
9271 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009272 // rrx is a special case encoding of ror (immediate)
9273 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9274 // ror (immediate)
9275 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9276 // ror (register)
9277 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009278 // mul
9279 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009280
9281 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009282 // Load instructions
9283 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009284 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009285 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009286 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009287 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009288 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009289 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009290 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009291 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009292 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009293 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009294 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009295 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009296 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009297 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009298 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9299 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009300
9301 //----------------------------------------------------------------------
9302 // Store instructions
9303 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009304 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009305 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009306 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009307 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009308 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009309 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009310
Caroline Tice6bf65162011-03-03 17:42:58 +00009311 //----------------------------------------------------------------------
9312 // Other instructions
9313 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009314 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009315 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009316 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009317 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9318 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009319
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009320 };
9321 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9322
9323 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9324 {
9325 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9326 return &g_arm_opcodes[i];
9327 }
9328 return NULL;
9329}
Greg Clayton64c84432011-01-21 22:02:52 +00009330
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009331
9332EmulateInstructionARM::ARMOpcode*
9333EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009334{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009335
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009336 static ARMOpcode
9337 g_thumb_opcodes[] =
9338 {
9339 //----------------------------------------------------------------------
9340 // Prologue instructions
9341 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009342
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009343 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009344 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9345 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9346 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009347
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009348 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009349 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009350 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009351 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009352 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009353 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009354
Johnny Chen864a8e82011-02-18 00:07:39 +00009355 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009356 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009357
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009358 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009359 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009360 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009361 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9362 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009363
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009364 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009365 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9366 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009367
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009368 //----------------------------------------------------------------------
9369 // Epilogue instructions
9370 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009371
Caroline Ticee2212882011-03-22 22:38:28 +00009372 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009373 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009374 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9375 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9376 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009377 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9378 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009379
9380 //----------------------------------------------------------------------
9381 // Supervisor Call (previously Software Interrupt)
9382 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009383 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9384
9385 //----------------------------------------------------------------------
9386 // If Then makes up to four following instructions conditional.
9387 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009388 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9389
9390 //----------------------------------------------------------------------
9391 // Branch instructions
9392 //----------------------------------------------------------------------
9393 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9394 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +00009395 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009396 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009397 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009398 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009399 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009400 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +00009401 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +00009402 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009403 // for example, "bx lr"
9404 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009405 // bxj
9406 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009407 // compare and branch
9408 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009409 // table branch byte
9410 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9411 // table branch halfword
9412 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009413
9414 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009415 // Data-processing instructions
9416 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009417 // adc (immediate)
9418 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9419 // adc (register)
9420 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9421 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9422 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009423 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009424 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009425 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009426 // adr
9427 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9428 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9429 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009430 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009431 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009432 // and (register)
9433 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9434 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009435 // bic (immediate)
9436 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9437 // bic (register)
9438 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9439 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009440 // eor (immediate)
9441 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9442 // eor (register)
9443 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9444 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009445 // orr (immediate)
9446 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9447 // orr (register)
9448 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9449 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009450 // rsb (immediate)
9451 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9452 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9453 // rsb (register)
9454 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009455 // sbc (immediate)
9456 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9457 // sbc (register)
9458 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9459 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009460 // add (immediate, Thumb)
9461 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9462 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9463 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9464 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009465 // sub (immediate, Thumb)
9466 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9467 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9468 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9469 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009470 // sub (sp minus immediate)
9471 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9472 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009473 // teq (immediate)
9474 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9475 // teq (register)
9476 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009477 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009478 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009479 // tst (register)
9480 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9481 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9482
Johnny Chen7c5234d2011-02-18 23:41:11 +00009483
Johnny Chen338bf542011-02-10 19:29:03 +00009484 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009485 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009486 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009487 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009488 // mov{s}<c>.w <Rd>, <Rm>
9489 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009490 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009491 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9492 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009493 // mvn (immediate)
9494 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9495 // mvn (register)
9496 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9497 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009498 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009499 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009500 // cmn (register)
9501 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009502 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009503 // cmp (immediate)
9504 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009505 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009506 // cmp (register) (Rn and Rm both from r0-r7)
9507 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9508 // cmp (register) (Rn and Rm not both from r0-r7)
9509 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009510 // asr (immediate)
9511 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009512 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009513 // asr (register)
9514 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9515 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009516 // lsl (immediate)
9517 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9518 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9519 // lsl (register)
9520 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9521 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9522 // lsr (immediate)
9523 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9524 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9525 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009526 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009527 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009528 // rrx is a special case encoding of ror (immediate)
9529 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9530 // ror (immediate)
9531 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9532 // ror (register)
9533 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9534 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009535 // mul
9536 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9537 // mul
9538 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009539
Johnny Chen26863dc2011-02-09 23:43:29 +00009540 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009541 // Load instructions
9542 //----------------------------------------------------------------------
9543 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009544 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009545 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticebaf1f642011-03-24 19:23:45 +00009546 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9547 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
9548 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
9549 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
9550 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009551 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009552 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9553 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009554 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9555 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9556 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009557 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009558 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9559 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009560 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9561 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9562 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009563 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009564 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9565 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009566 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9567 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009568 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009569 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9570 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009571 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9572 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009573 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009574 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9575 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009576
9577 //----------------------------------------------------------------------
9578 // Store instructions
9579 //----------------------------------------------------------------------
9580 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009581 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009582 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009583 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9584 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9585 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9586 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9587 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9588 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9589 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9590 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009591 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009592 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9593 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009594
9595 //----------------------------------------------------------------------
9596 // Other instructions
9597 //----------------------------------------------------------------------
9598 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009599 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9600 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009601 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9602 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009603 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9604 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009605 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9606 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9607 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009608
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009609 };
9610
9611 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9612 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9613 {
9614 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9615 return &g_thumb_opcodes[i];
9616 }
9617 return NULL;
9618}
Greg Clayton64c84432011-01-21 22:02:52 +00009619
Greg Clayton31e2a382011-01-30 20:03:56 +00009620bool
Greg Clayton395fc332011-02-15 21:59:32 +00009621EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009622{
9623 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009624 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009625 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009626 {
Greg Clayton395fc332011-02-15 21:59:32 +00009627 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9628 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9629 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9630 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9631 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9632 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9633 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9634 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9635 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9636 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009637 }
9638 return m_arm_isa != 0;
9639}
9640
9641
Greg Clayton64c84432011-01-21 22:02:52 +00009642bool
9643EmulateInstructionARM::ReadInstruction ()
9644{
9645 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +00009646 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009647 if (success)
9648 {
9649 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9650 if (success)
9651 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009652 Context read_inst_context;
9653 read_inst_context.type = eContextReadOpcode;
9654 read_inst_context.SetNoArgs ();
9655
Greg Claytonb3448432011-03-24 21:19:54 +00009656 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +00009657 {
Greg Claytonb3448432011-03-24 21:19:54 +00009658 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009659 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009660
9661 if (success)
9662 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009663 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +00009664 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009665 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009666 }
9667 else
9668 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009669 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009670 }
9671 }
9672 }
9673 else
9674 {
Greg Claytonb3448432011-03-24 21:19:54 +00009675 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +00009676 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +00009677 }
9678 }
9679 }
9680 if (!success)
9681 {
Greg Claytonb3448432011-03-24 21:19:54 +00009682 m_opcode_mode = eModeInvalid;
9683 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +00009684 }
9685 return success;
9686}
9687
Johnny Chenee9b1f72011-02-09 01:00:31 +00009688uint32_t
9689EmulateInstructionARM::ArchVersion ()
9690{
9691 return m_arm_isa;
9692}
9693
Greg Clayton64c84432011-01-21 22:02:52 +00009694bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009695EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009696{
Greg Claytonb3448432011-03-24 21:19:54 +00009697 if (m_opcode_cpsr == 0)
Greg Clayton64c84432011-01-21 22:02:52 +00009698 return false;
9699
Greg Clayton7bc39082011-03-24 23:53:38 +00009700 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +00009701
9702 if (cond == UINT32_MAX)
9703 return false;
9704
9705 bool result = false;
9706 switch (UnsignedBits(cond, 3, 1))
9707 {
Greg Claytonb3448432011-03-24 21:19:54 +00009708 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
9709 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
9710 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
9711 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
9712 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 +00009713 case 5:
9714 {
Greg Claytonb3448432011-03-24 21:19:54 +00009715 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9716 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +00009717 result = n == v;
9718 }
9719 break;
9720 case 6:
9721 {
Greg Claytonb3448432011-03-24 21:19:54 +00009722 bool n = (m_opcode_cpsr & MASK_CPSR_N);
9723 bool v = (m_opcode_cpsr & MASK_CPSR_V);
9724 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +00009725 }
9726 break;
9727 case 7:
9728 result = true;
9729 break;
9730 }
9731
9732 if (cond & 1)
9733 result = !result;
9734 return result;
9735}
9736
Johnny Chen9ee056b2011-02-08 00:06:35 +00009737uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +00009738EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009739{
Greg Claytonb3448432011-03-24 21:19:54 +00009740 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009741 {
9742 default:
9743 case eModeInvalid:
9744 break;
9745
9746 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +00009747 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009748
9749 case eModeThumb:
9750 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9751 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +00009752 {
Greg Clayton7bc39082011-03-24 23:53:38 +00009753 const uint32_t byte_size = m_opcode.GetByteSize();
9754 if (byte_size == 2)
9755 {
9756 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
9757 return Bits32(opcode, 11, 7);
9758 }
9759 else
9760 {
9761 assert (byte_size == 4);
9762 if (Bits32(opcode, 31, 27) == 0x1e &&
9763 Bits32(opcode, 15, 14) == 0x02 &&
9764 Bits32(opcode, 12, 12) == 0x00 &&
9765 Bits32(opcode, 25, 22) <= 0x0d)
9766 {
9767 return Bits32(opcode, 25, 22);
9768 }
9769 }
9770
9771 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +00009772 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009773 }
9774 return UINT32_MAX; // Return invalid value
9775}
9776
Johnny Chen9ee056b2011-02-08 00:06:35 +00009777bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009778EmulateInstructionARM::InITBlock()
9779{
9780 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9781}
9782
9783bool
9784EmulateInstructionARM::LastInITBlock()
9785{
9786 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9787}
9788
Caroline Ticeb27771d2011-03-03 22:37:46 +00009789bool
9790EmulateInstructionARM::BadMode (uint32_t mode)
9791{
9792
9793 switch (mode)
9794 {
9795 case 16: return false; // '10000'
9796 case 17: return false; // '10001'
9797 case 18: return false; // '10010'
9798 case 19: return false; // '10011'
9799 case 22: return false; // '10110'
9800 case 23: return false; // '10111'
9801 case 27: return false; // '11011'
9802 case 31: return false; // '11111'
9803 default: return true;
9804 }
9805 return true;
9806}
9807
9808bool
9809EmulateInstructionARM::CurrentModeIsPrivileged ()
9810{
Greg Claytonb3448432011-03-24 21:19:54 +00009811 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009812
9813 if (BadMode (mode))
9814 return false;
9815
9816 if (mode == 16)
9817 return false;
9818
9819 return true;
9820}
9821
9822void
9823EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9824{
9825 bool privileged = CurrentModeIsPrivileged();
9826
9827 uint32_t tmp_cpsr = 0;
9828
Greg Claytonb3448432011-03-24 21:19:54 +00009829 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +00009830
9831 if (BitIsSet (bytemask, 3))
9832 {
9833 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
9834 if (affect_execstate)
9835 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
9836 }
9837
9838 if (BitIsSet (bytemask, 2))
9839 {
9840 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
9841 }
9842
9843 if (BitIsSet (bytemask, 1))
9844 {
9845 if (affect_execstate)
9846 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
9847 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
9848 if (privileged)
9849 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
9850 }
9851
9852 if (BitIsSet (bytemask, 0))
9853 {
9854 if (privileged)
9855 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
9856 if (affect_execstate)
9857 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
9858 if (privileged)
9859 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
9860 }
9861
Greg Claytonb3448432011-03-24 21:19:54 +00009862 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +00009863}
9864
9865
Johnny Chen098ae2d2011-02-12 00:50:05 +00009866bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009867EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9868{
9869 addr_t target;
9870
Johnny Chenee9b1f72011-02-09 01:00:31 +00009871 // Check the current instruction set.
9872 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009873 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009874 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009875 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009876
Johnny Chen9ee056b2011-02-08 00:06:35 +00009877 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009878 return false;
9879
9880 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009881}
9882
9883// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9884bool
Johnny Chen668b4512011-02-15 21:08:58 +00009885EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009886{
9887 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009888 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9889 // we want to record it and issue a WriteRegister callback so the clients
9890 // can track the mode changes accordingly.
9891 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009892
9893 if (BitIsSet(addr, 0))
9894 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009895 if (CurrentInstrSet() != eModeThumb)
9896 {
9897 SelectInstrSet(eModeThumb);
9898 cpsr_changed = true;
9899 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009900 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009901 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009902 }
9903 else if (BitIsClear(addr, 1))
9904 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009905 if (CurrentInstrSet() != eModeARM)
9906 {
9907 SelectInstrSet(eModeARM);
9908 cpsr_changed = true;
9909 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009910 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009911 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009912 }
9913 else
9914 return false; // address<1:0> == '10' => UNPREDICTABLE
9915
Johnny Chen0f309db2011-02-09 19:11:32 +00009916 if (cpsr_changed)
9917 {
Johnny Chen558133b2011-02-09 23:59:17 +00009918 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009919 return false;
9920 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009921 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009922 return false;
9923
9924 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009925}
Greg Clayton64c84432011-01-21 22:02:52 +00009926
Johnny Chenee9b1f72011-02-09 01:00:31 +00009927// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9928bool
Johnny Chen668b4512011-02-15 21:08:58 +00009929EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009930{
9931 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009932 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009933 else
9934 return BranchWritePC((const Context)context, addr);
9935}
9936
Johnny Chen26863dc2011-02-09 23:43:29 +00009937// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9938bool
Johnny Chen668b4512011-02-15 21:08:58 +00009939EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009940{
9941 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009942 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009943 else
9944 return BranchWritePC((const Context)context, addr);
9945}
9946
Johnny Chenee9b1f72011-02-09 01:00:31 +00009947EmulateInstructionARM::Mode
9948EmulateInstructionARM::CurrentInstrSet ()
9949{
Greg Claytonb3448432011-03-24 21:19:54 +00009950 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009951}
9952
Greg Claytonb3448432011-03-24 21:19:54 +00009953// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009954// ReadInstruction() is performed. This function has a side effect of updating
9955// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009956bool
9957EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9958{
Greg Claytonb3448432011-03-24 21:19:54 +00009959 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009960 switch (arm_or_thumb)
9961 {
9962 default:
9963 return false;
9964 eModeARM:
9965 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009966 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009967 break;
9968 eModeThumb:
9969 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009970 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009971 break;
9972 }
9973 return true;
9974}
9975
Johnny Chenef21b592011-02-10 01:52:38 +00009976// This function returns TRUE if the processor currently provides support for
9977// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9978// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9979bool
9980EmulateInstructionARM::UnalignedSupport()
9981{
9982 return (ArchVersion() >= ARMv7);
9983}
9984
Johnny Chenbf6ad172011-02-11 01:29:53 +00009985// The main addition and subtraction instructions can produce status information
9986// about both unsigned carry and signed overflow conditions. This status
9987// information can be used to synthesize multi-word additions and subtractions.
9988EmulateInstructionARM::AddWithCarryResult
9989EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9990{
9991 uint32_t result;
9992 uint8_t carry_out;
9993 uint8_t overflow;
9994
9995 uint64_t unsigned_sum = x + y + carry_in;
9996 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9997
9998 result = UnsignedBits(unsigned_sum, 31, 0);
9999 carry_out = (result == unsigned_sum ? 0 : 1);
10000 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10001
10002 AddWithCarryResult res = { result, carry_out, overflow };
10003 return res;
10004}
10005
Johnny Chen157b9592011-02-18 21:13:05 +000010006uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010007EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010008{
Johnny Chene39f22d2011-02-19 01:36:13 +000010009 uint32_t reg_kind, reg_num;
10010 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010011 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010012 case SP_REG:
10013 reg_kind = eRegisterKindGeneric;
10014 reg_num = LLDB_REGNUM_GENERIC_SP;
10015 break;
10016 case LR_REG:
10017 reg_kind = eRegisterKindGeneric;
10018 reg_num = LLDB_REGNUM_GENERIC_RA;
10019 break;
10020 case PC_REG:
10021 reg_kind = eRegisterKindGeneric;
10022 reg_num = LLDB_REGNUM_GENERIC_PC;
10023 break;
10024 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010025 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010026 {
10027 reg_kind = eRegisterKindDWARF;
10028 reg_num = dwarf_r0 + num;
10029 }
Johnny Chen157b9592011-02-18 21:13:05 +000010030 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010031 {
10032 assert(0 && "Invalid register number");
10033 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010034 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010035 }
10036 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010037 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010038
10039 // Read our register.
10040 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10041
10042 // When executing an ARM instruction , PC reads as the address of the current
10043 // instruction plus 8.
10044 // When executing a Thumb instruction , PC reads as the address of the current
10045 // instruction plus 4.
10046 if (num == 15)
10047 {
10048 if (CurrentInstrSet() == eModeARM)
10049 val += 8;
10050 else
10051 val += 4;
10052 }
Johnny Chen157b9592011-02-18 21:13:05 +000010053
10054 return val;
10055}
10056
Johnny Chenca67d1c2011-02-17 01:35:27 +000010057// Write the result to the ARM core register Rd, and optionally update the
10058// condition flags based on the result.
10059//
10060// This helper method tries to encapsulate the following pseudocode from the
10061// ARM Architecture Reference Manual:
10062//
10063// if d == 15 then // Can only occur for encoding A1
10064// ALUWritePC(result); // setflags is always FALSE here
10065// else
10066// R[d] = result;
10067// if setflags then
10068// APSR.N = result<31>;
10069// APSR.Z = IsZeroBit(result);
10070// APSR.C = carry;
10071// // APSR.V unchanged
10072//
10073// In the above case, the API client does not pass in the overflow arg, which
10074// defaults to ~0u.
10075bool
Johnny Chen10530c22011-02-17 22:37:12 +000010076EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10077 const uint32_t result,
10078 const uint32_t Rd,
10079 bool setflags,
10080 const uint32_t carry,
10081 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010082{
10083 if (Rd == 15)
10084 {
10085 if (!ALUWritePC (context, result))
10086 return false;
10087 }
10088 else
10089 {
Johnny Chena695f952011-02-23 21:24:25 +000010090 uint32_t reg_kind, reg_num;
10091 switch (Rd)
10092 {
10093 case SP_REG:
10094 reg_kind = eRegisterKindGeneric;
10095 reg_num = LLDB_REGNUM_GENERIC_SP;
10096 break;
10097 case LR_REG:
10098 reg_kind = eRegisterKindGeneric;
10099 reg_num = LLDB_REGNUM_GENERIC_RA;
10100 break;
10101 default:
10102 reg_kind = eRegisterKindDWARF;
10103 reg_num = dwarf_r0 + Rd;
10104 }
10105 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010106 return false;
10107 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010108 return WriteFlags (context, result, carry, overflow);
10109 }
10110 return true;
10111}
10112
10113// This helper method tries to encapsulate the following pseudocode from the
10114// ARM Architecture Reference Manual:
10115//
10116// APSR.N = result<31>;
10117// APSR.Z = IsZeroBit(result);
10118// APSR.C = carry;
10119// APSR.V = overflow
10120//
10121// Default arguments can be specified for carry and overflow parameters, which means
10122// not to update the respective flags.
10123bool
10124EmulateInstructionARM::WriteFlags (Context &context,
10125 const uint32_t result,
10126 const uint32_t carry,
10127 const uint32_t overflow)
10128{
Greg Claytonb3448432011-03-24 21:19:54 +000010129 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010130 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10131 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010132 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010133 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010134 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010135 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000010136 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000010137 {
10138 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10139 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010140 }
10141 return true;
10142}
10143
Greg Clayton64c84432011-01-21 22:02:52 +000010144bool
10145EmulateInstructionARM::EvaluateInstruction ()
10146{
Johnny Chenc315f862011-02-05 00:46:10 +000010147 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000010148 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000010149 m_it_session.ITAdvance();
10150
Greg Clayton64c84432011-01-21 22:02:52 +000010151 return false;
10152}