blob: c4a6be5074fca8df665659047d8077ef82a9900b [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000133#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000134
Johnny Chen0e00af22011-02-10 19:40:42 +0000135//----------------------------------------------------------------------
136//
137// EmulateInstructionARM implementation
138//
139//----------------------------------------------------------------------
140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000145
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000146void
147EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000148{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000149}
150
Caroline Ticefa172202011-02-11 22:49:54 +0000151// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
152bool
153EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
154{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000155 EmulateInstruction::Context context;
156 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
157 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000158
159 uint32_t random_data = rand ();
160 const uint32_t addr_byte_size = GetAddressByteSize();
161
Caroline Ticecc96eb52011-02-17 19:20:40 +0000162 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000163 return false;
164
165 return true;
166}
167
Caroline Tice713c2662011-02-11 17:59:55 +0000168// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
169bool
170EmulateInstructionARM::WriteBits32Unknown (int n)
171{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000172 EmulateInstruction::Context context;
173 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
174 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000175
Johnny Chen62ff6f52011-02-11 18:11:22 +0000176 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000177 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
178
179 if (!success)
180 return false;
181
182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
183 return false;
184
185 return true;
186}
187
Johnny Chen08c25e82011-01-31 18:02:28 +0000188// Push Multiple Registers stores multiple registers to the stack, storing to
189// consecutive memory locations ending just below the address in SP, and updates
190// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000191bool
Johnny Chen9f687722011-02-18 00:02:28 +0000192EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000193{
194#if 0
195 // ARM pseudo code...
196 if (ConditionPassed())
197 {
198 EncodingSpecificOperations();
199 NullCheckIfThumbEE(13);
200 address = SP - 4*BitCount(registers);
201
202 for (i = 0 to 14)
203 {
204 if (registers<i> == ’1’)
205 {
206 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
207 MemA[address,4] = bits(32) UNKNOWN;
208 else
209 MemA[address,4] = R[i];
210 address = address + 4;
211 }
212 }
213
214 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
215 MemA[address,4] = PCStoreValue();
216
217 SP = SP - 4*BitCount(registers);
218 }
219#endif
220
221 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000222 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000223 if (!success)
224 return false;
225
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000226 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000227 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000229 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000230 if (!success)
231 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000232 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000233 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000234 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000236 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000238 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000239 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000240 // if BitCount(registers) < 1 then UNPREDICTABLE;
241 if (BitCount(registers) < 1)
242 return false;
243 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 case eEncodingT2:
245 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000246 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000247 // if BitCount(registers) < 2 then UNPREDICTABLE;
248 if (BitCount(registers) < 2)
249 return false;
250 break;
251 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000252 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000253 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000254 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000255 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000256 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000257 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000258 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000259 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000260 // Instead of return false, let's handle the following case as well,
261 // which amounts to pushing one reg onto the full descending stacks.
262 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000263 break;
264 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000265 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000266 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000267 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000269 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000271 default:
272 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000273 }
Johnny Chence1ca772011-01-25 01:13:00 +0000274 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000275 addr_t addr = sp - sp_offset;
276 uint32_t i;
277
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000278 EmulateInstruction::Context context;
279 context.type = EmulateInstruction::eContextPushRegisterOnStack;
280 Register dwarf_reg;
281 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000282 for (i=0; i<15; ++i)
283 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000284 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000285 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000286 dwarf_reg.num = dwarf_r0 + i;
287 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000288 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000289 if (!success)
290 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000291 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 return false;
293 addr += addr_byte_size;
294 }
295 }
296
Johnny Chen7c1bf922011-02-08 23:49:37 +0000297 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000298 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000299 dwarf_reg.num = dwarf_pc;
300 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000301 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000302 if (!success)
303 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000305 return false;
306 }
307
308 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000309 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000310
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000311 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000312 return false;
313 }
314 return true;
315}
316
Johnny Chenef85e912011-01-31 23:07:40 +0000317// Pop Multiple Registers loads multiple registers from the stack, loading from
318// consecutive memory locations staring at the address in SP, and updates
319// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000320bool
Johnny Chen9f687722011-02-18 00:02:28 +0000321EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000322{
323#if 0
324 // ARM pseudo code...
325 if (ConditionPassed())
326 {
327 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
328 address = SP;
329 for i = 0 to 14
330 if registers<i> == ‘1’ then
331 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
332 if registers<15> == ‘1’ then
333 if UnalignedAllowed then
334 LoadWritePC(MemU[address,4]);
335 else
336 LoadWritePC(MemA[address,4]);
337 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
338 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
339 }
340#endif
341
342 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000344 if (!success)
345 return false;
346
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000347 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000348 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000349 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000350 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000351 if (!success)
352 return false;
353 uint32_t registers = 0;
354 uint32_t Rt; // the destination register
355 switch (encoding) {
356 case eEncodingT1:
357 registers = Bits32(opcode, 7, 0);
358 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000359 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000360 registers |= (1u << 15);
361 // if BitCount(registers) < 1 then UNPREDICTABLE;
362 if (BitCount(registers) < 1)
363 return false;
364 break;
365 case eEncodingT2:
366 // Ignore bit 13.
367 registers = Bits32(opcode, 15, 0) & ~0x2000;
368 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000369 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000370 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000371 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
372 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
373 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000374 break;
375 case eEncodingT3:
376 Rt = Bits32(opcode, 15, 12);
377 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000378 if (Rt == 13)
379 return false;
380 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000381 return false;
382 registers = (1u << Rt);
383 break;
384 case eEncodingA1:
385 registers = Bits32(opcode, 15, 0);
386 // Instead of return false, let's handle the following case as well,
387 // which amounts to popping one reg from the full descending stacks.
388 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
389
390 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000391 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000392 return false;
393 break;
394 case eEncodingA2:
395 Rt = Bits32(opcode, 15, 12);
396 // if t == 13 then UNPREDICTABLE;
397 if (Rt == dwarf_sp)
398 return false;
399 registers = (1u << Rt);
400 break;
401 default:
402 return false;
403 }
404 addr_t sp_offset = addr_byte_size * BitCount (registers);
405 addr_t addr = sp;
406 uint32_t i, data;
407
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000408 EmulateInstruction::Context context;
409 context.type = EmulateInstruction::eContextPopRegisterOffStack;
410 Register dwarf_reg;
411 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000412 for (i=0; i<15; ++i)
413 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000414 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000415 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000416 dwarf_reg.num = dwarf_r0 + i;
417 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000418 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000419 if (!success)
420 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000421 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000422 return false;
423 addr += addr_byte_size;
424 }
425 }
426
Johnny Chen7c1bf922011-02-08 23:49:37 +0000427 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000428 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000429 dwarf_reg.num = dwarf_pc;
430 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000431 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000432 if (!success)
433 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000434 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000435 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000436 return false;
437 addr += addr_byte_size;
438 }
439
440 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000441 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000442
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000443 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000444 return false;
445 }
446 return true;
447}
448
Johnny Chen5b442b72011-01-27 19:34:30 +0000449// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000450// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000451bool
Johnny Chen9f687722011-02-18 00:02:28 +0000452EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000453{
454#if 0
455 // ARM pseudo code...
456 if (ConditionPassed())
457 {
458 EncodingSpecificOperations();
459 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
460 if d == 15 then
461 ALUWritePC(result); // setflags is always FALSE here
462 else
463 R[d] = result;
464 if setflags then
465 APSR.N = result<31>;
466 APSR.Z = IsZeroBit(result);
467 APSR.C = carry;
468 APSR.V = overflow;
469 }
470#endif
471
472 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000474 if (!success)
475 return false;
476
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000477 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000478 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000479 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000480 if (!success)
481 return false;
482 uint32_t Rd; // the destination register
483 uint32_t imm32;
484 switch (encoding) {
485 case eEncodingT1:
486 Rd = 7;
487 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
488 break;
489 case eEncodingA1:
490 Rd = Bits32(opcode, 15, 12);
491 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
492 break;
493 default:
494 return false;
495 }
496 addr_t sp_offset = imm32;
497 addr_t addr = sp + sp_offset; // a pointer to the stack area
498
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000499 EmulateInstruction::Context context;
500 context.type = EmulateInstruction::eContextRegisterPlusOffset;
501 Register sp_reg;
502 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
503 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000504
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000506 return false;
507 }
508 return true;
509}
510
Johnny Chen2ccad832011-01-28 19:57:25 +0000511// Set r7 or ip to the current stack pointer.
512// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000513bool
Johnny Chen9f687722011-02-18 00:02:28 +0000514EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000515{
516#if 0
517 // ARM pseudo code...
518 if (ConditionPassed())
519 {
520 EncodingSpecificOperations();
521 result = R[m];
522 if d == 15 then
523 ALUWritePC(result); // setflags is always FALSE here
524 else
525 R[d] = result;
526 if setflags then
527 APSR.N = result<31>;
528 APSR.Z = IsZeroBit(result);
529 // APSR.C unchanged
530 // APSR.V unchanged
531 }
532#endif
533
534 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000536 //if (!success)
537 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000538
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000539 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000540 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000541 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000542 if (!success)
543 return false;
544 uint32_t Rd; // the destination register
545 switch (encoding) {
546 case eEncodingT1:
547 Rd = 7;
548 break;
549 case eEncodingA1:
550 Rd = 12;
551 break;
552 default:
553 return false;
554 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000555
556 EmulateInstruction::Context context;
557 context.type = EmulateInstruction::eContextRegisterPlusOffset;
558 Register sp_reg;
559 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
560 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000561
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000563 return false;
564 }
565 return true;
566}
567
Johnny Chen1c13b622011-01-29 00:11:15 +0000568// Move from high register (r8-r15) to low register (r0-r7).
569// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000570bool
Johnny Chen9f687722011-02-18 00:02:28 +0000571EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000572{
Johnny Chen9f687722011-02-18 00:02:28 +0000573 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000574}
575
576// Move from register to register.
577// MOV (register)
578bool
Johnny Chen9f687722011-02-18 00:02:28 +0000579EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000580{
Johnny Chen1c13b622011-01-29 00:11:15 +0000581#if 0
582 // ARM pseudo code...
583 if (ConditionPassed())
584 {
585 EncodingSpecificOperations();
586 result = R[m];
587 if d == 15 then
588 ALUWritePC(result); // setflags is always FALSE here
589 else
590 R[d] = result;
591 if setflags then
592 APSR.N = result<31>;
593 APSR.Z = IsZeroBit(result);
594 // APSR.C unchanged
595 // APSR.V unchanged
596 }
597#endif
598
599 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000600 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 if (!success)
602 return false;
603
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000604 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000605 {
606 uint32_t Rm; // the source register
607 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000608 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000609 switch (encoding) {
610 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000611 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000612 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000613 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000614 if (Rd == 15 && InITBlock() && !LastInITBlock())
615 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000616 break;
617 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000618 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000620 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000621 if (InITBlock())
622 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000623 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000624 case eEncodingT3:
625 Rd = Bits32(opcode, 11, 8);
626 Rm = Bits32(opcode, 3, 0);
627 setflags = BitIsSet(opcode, 20);
628 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
629 if (setflags && (BadReg(Rd) || BadReg(Rm)))
630 return false;
631 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
632 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
633 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000634 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000635 case eEncodingA1:
636 Rd = Bits32(opcode, 15, 12);
637 Rm = Bits32(opcode, 3, 0);
638 setflags = BitIsSet(opcode, 20);
639 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
640 // TODO: Emulate SUBS PC, LR and related instructions.
641 if (Rd == 15 && setflags)
642 return false;
643 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000644 default:
645 return false;
646 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000647 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000648 if (!success)
649 return false;
650
651 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000652 EmulateInstruction::Context context;
653 context.type = EmulateInstruction::eContextRegisterPlusOffset;
654 Register dwarf_reg;
655 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
656 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000657
Johnny Chen10530c22011-02-17 22:37:12 +0000658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000659 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000660 }
661 return true;
662}
663
Johnny Chen357c30f2011-02-14 22:04:25 +0000664// Move (immediate) writes an immediate value to the destination register. It
665// can optionally update the condition flags based on the value.
666// MOV (immediate)
667bool
Johnny Chen9f687722011-02-18 00:02:28 +0000668EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000669{
670#if 0
671 // ARM pseudo code...
672 if (ConditionPassed())
673 {
674 EncodingSpecificOperations();
675 result = imm32;
676 if d == 15 then // Can only occur for ARM encoding
677 ALUWritePC(result); // setflags is always FALSE here
678 else
679 R[d] = result;
680 if setflags then
681 APSR.N = result<31>;
682 APSR.Z = IsZeroBit(result);
683 APSR.C = carry;
684 // APSR.V unchanged
685 }
686#endif
687 bool success = false;
688 const uint32_t opcode = OpcodeAsUnsigned (&success);
689 if (!success)
690 return false;
691
692 if (ConditionPassed())
693 {
694 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000695 uint32_t imm32; // the immediate value to be written to Rd
696 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
697 bool setflags;
698 switch (encoding) {
699 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000700 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000701 setflags = !InITBlock();
702 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000703 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000704 break;
705 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000706 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000707 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000708 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000709 if (BadReg(Rd))
710 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000711 break;
712 default:
713 return false;
714 }
715 uint32_t result = imm32;
716
717 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000718 EmulateInstruction::Context context;
719 context.type = EmulateInstruction::eContextImmediate;
720 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000721
Johnny Chen10530c22011-02-17 22:37:12 +0000722 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000723 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000724 }
725 return true;
726}
727
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000728// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
729// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
730// unsigned values.
731//
732// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
733// limited to only a few forms of the instruction.
734bool
735EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
736{
737#if 0
738 if ConditionPassed() then
739 EncodingSpecificOperations();
740 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
741 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
742 result = operand1 * operand2;
743 R[d] = result<31:0>;
744 if setflags then
745 APSR.N = result<31>;
746 APSR.Z = IsZeroBit(result);
747 if ArchVersion() == 4 then
748 APSR.C = bit UNKNOWN;
749 // else APSR.C unchanged
750 // APSR.V always unchanged
751#endif
752
753 bool success = false;
754 const uint32_t opcode = OpcodeAsUnsigned (&success);
755 if (!success)
756 return false;
757
758 if (ConditionPassed())
759 {
760 uint32_t d;
761 uint32_t n;
762 uint32_t m;
763 bool setflags;
764
765 // EncodingSpecificOperations();
766 switch (encoding)
767 {
768 case eEncodingT1:
769 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
770 d = Bits32 (opcode, 2, 0);
771 n = Bits32 (opcode, 5, 3);
772 m = Bits32 (opcode, 2, 0);
773 setflags = !InITBlock();
774
775 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
776 if ((ArchVersion() < ARMv6) && (d == n))
777 return false;
778
779 break;
780
781 case eEncodingT2:
782 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
783 d = Bits32 (opcode, 11, 8);
784 n = Bits32 (opcode, 19, 16);
785 m = Bits32 (opcode, 3, 0);
786 setflags = false;
787
788 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
789 if (BadReg (d) || BadReg (n) || BadReg (m))
790 return false;
791
792 break;
793
794 case eEncodingA1:
795 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
796 d = Bits32 (opcode, 19, 16);
797 n = Bits32 (opcode, 3, 0);
798 m = Bits32 (opcode, 11, 8);
799 setflags = BitIsSet (opcode, 20);
800
801 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
802 if ((d == 15) || (n == 15) || (m == 15))
803 return false;
804
805 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
806 if ((ArchVersion() < ARMv6) && (d == n))
807 return false;
808
809 break;
810
811 default:
812 return false;
813 }
814
815 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
816 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
817 if (!success)
818 return false;
819
820 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
821 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
822 if (!success)
823 return false;
824
825 // result = operand1 * operand2;
826 uint64_t result = operand1 * operand2;
827
828 // R[d] = result<31:0>;
829 Register op1_reg;
830 Register op2_reg;
831 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
832 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
833
834 EmulateInstruction::Context context;
835 context.type = eContextMultiplication;
836 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
837
838 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
839 return false;
840
841 // if setflags then
842 if (setflags)
843 {
844 // APSR.N = result<31>;
845 // APSR.Z = IsZeroBit(result);
846 m_new_inst_cpsr = m_inst_cpsr;
847 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
848 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
849 if (m_new_inst_cpsr != m_inst_cpsr)
850 {
851 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
852 return false;
853 }
854
855 // if ArchVersion() == 4 then
856 // APSR.C = bit UNKNOWN;
857 }
858 }
859 return true;
860}
861
Johnny Chend642a6a2011-02-22 01:01:03 +0000862// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
863// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000864bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000865EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000866{
867#if 0
868 // ARM pseudo code...
869 if (ConditionPassed())
870 {
871 EncodingSpecificOperations();
872 result = NOT(imm32);
873 if d == 15 then // Can only occur for ARM encoding
874 ALUWritePC(result); // setflags is always FALSE here
875 else
876 R[d] = result;
877 if setflags then
878 APSR.N = result<31>;
879 APSR.Z = IsZeroBit(result);
880 APSR.C = carry;
881 // APSR.V unchanged
882 }
883#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000884 bool success = false;
885 const uint32_t opcode = OpcodeAsUnsigned (&success);
886 if (!success)
887 return false;
888
889 if (ConditionPassed())
890 {
891 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000892 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
893 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000894 bool setflags;
895 switch (encoding) {
896 case eEncodingT1:
897 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000898 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000899 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000900 break;
901 case eEncodingA1:
902 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000904 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
905 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
906 // TODO: Emulate SUBS PC, LR and related instructions.
907 if (Rd == 15 && setflags)
908 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000909 break;
910 default:
911 return false;
912 }
913 uint32_t result = ~imm32;
914
915 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000916 EmulateInstruction::Context context;
917 context.type = EmulateInstruction::eContextImmediate;
918 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000919
Johnny Chen10530c22011-02-17 22:37:12 +0000920 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000921 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000922 }
923 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000924}
925
Johnny Chend642a6a2011-02-22 01:01:03 +0000926// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
927// It can optionally update the condition flags based on the result.
928bool
929EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
930{
931#if 0
932 // ARM pseudo code...
933 if (ConditionPassed())
934 {
935 EncodingSpecificOperations();
936 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
937 result = NOT(shifted);
938 if d == 15 then // Can only occur for ARM encoding
939 ALUWritePC(result); // setflags is always FALSE here
940 else
941 R[d] = result;
942 if setflags then
943 APSR.N = result<31>;
944 APSR.Z = IsZeroBit(result);
945 APSR.C = carry;
946 // APSR.V unchanged
947 }
948#endif
949
950 bool success = false;
951 const uint32_t opcode = OpcodeAsUnsigned (&success);
952 if (!success)
953 return false;
954
955 if (ConditionPassed())
956 {
957 uint32_t Rm; // the source register
958 uint32_t Rd; // the destination register
959 ARM_ShifterType shift_t;
960 uint32_t shift_n; // the shift applied to the value read from Rm
961 bool setflags;
962 uint32_t carry; // the carry bit after the shift operation
963 switch (encoding) {
964 case eEncodingT1:
965 Rd = Bits32(opcode, 2, 0);
966 Rm = Bits32(opcode, 5, 3);
967 setflags = !InITBlock();
968 shift_t = SRType_LSL;
969 shift_n = 0;
970 if (InITBlock())
971 return false;
972 break;
973 case eEncodingT2:
974 Rd = Bits32(opcode, 11, 8);
975 Rm = Bits32(opcode, 3, 0);
976 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000977 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000978 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000979 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000980 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000981 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000982 case eEncodingA1:
983 Rd = Bits32(opcode, 15, 12);
984 Rm = Bits32(opcode, 3, 0);
985 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000986 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000987 break;
988 default:
989 return false;
990 }
991 uint32_t value = ReadCoreReg(Rm, &success);
992 if (!success)
993 return false;
994
995 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
996 uint32_t result = ~shifted;
997
998 // The context specifies that an immediate is to be moved into Rd.
999 EmulateInstruction::Context context;
1000 context.type = EmulateInstruction::eContextImmediate;
1001 context.SetNoArgs ();
1002
1003 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1004 return false;
1005 }
1006 return true;
1007}
1008
Johnny Chen788e0552011-01-27 22:52:23 +00001009// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1010// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001011bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001012EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001013{
1014#if 0
1015 // ARM pseudo code...
1016 if (ConditionPassed())
1017 {
1018 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1019 base = Align(PC,4);
1020 address = if add then (base + imm32) else (base - imm32);
1021 data = MemU[address,4];
1022 if t == 15 then
1023 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1024 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1025 R[t] = data;
1026 else // Can only apply before ARMv7
1027 if CurrentInstrSet() == InstrSet_ARM then
1028 R[t] = ROR(data, 8*UInt(address<1:0>));
1029 else
1030 R[t] = bits(32) UNKNOWN;
1031 }
1032#endif
1033
1034 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001035 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001036 if (!success)
1037 return false;
1038
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001039 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001040 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001041 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001042 if (!success)
1043 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001044
1045 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001046 EmulateInstruction::Context context;
1047 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1048 Register pc_reg;
1049 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1050 context.SetRegisterPlusOffset (pc_reg, 0);
1051
Johnny Chenc9de9102011-02-11 19:12:30 +00001052 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001053 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001054 bool add; // +imm32 or -imm32?
1055 addr_t base; // the base address
1056 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001057 uint32_t data; // the literal data value from the PC relative load
1058 switch (encoding) {
1059 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001060 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001061 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001062 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001063 break;
1064 case eEncodingT2:
1065 Rt = Bits32(opcode, 15, 12);
1066 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1067 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001068 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001069 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001070 break;
1071 default:
1072 return false;
1073 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001074
Johnny Chene39f22d2011-02-19 01:36:13 +00001075 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001076 if (add)
1077 address = base + imm32;
1078 else
1079 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001080
1081 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001082 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001083 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001084 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001085
1086 if (Rt == 15)
1087 {
1088 if (Bits32(address, 1, 0) == 0)
1089 {
1090 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001091 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001092 return false;
1093 }
1094 else
1095 return false;
1096 }
1097 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1098 {
1099 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1100 return false;
1101 }
1102 else // We don't handle ARM for now.
1103 return false;
1104
1105 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001106 return false;
1107 }
1108 return true;
1109}
1110
Johnny Chen5b442b72011-01-27 19:34:30 +00001111// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001112// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001113bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001114EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001115{
1116#if 0
1117 // ARM pseudo code...
1118 if (ConditionPassed())
1119 {
1120 EncodingSpecificOperations();
1121 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1122 if d == 15 then // Can only occur for ARM encoding
1123 ALUWritePC(result); // setflags is always FALSE here
1124 else
1125 R[d] = result;
1126 if setflags then
1127 APSR.N = result<31>;
1128 APSR.Z = IsZeroBit(result);
1129 APSR.C = carry;
1130 APSR.V = overflow;
1131 }
1132#endif
1133
1134 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001135 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001136 if (!success)
1137 return false;
1138
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001139 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001140 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001141 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001142 if (!success)
1143 return false;
1144 uint32_t imm32; // the immediate operand
1145 switch (encoding) {
1146 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001147 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001148 break;
1149 default:
1150 return false;
1151 }
1152 addr_t sp_offset = imm32;
1153 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1154
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001155 EmulateInstruction::Context context;
1156 context.type = EmulateInstruction::eContextAdjustStackPointer;
1157 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001158
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001159 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001160 return false;
1161 }
1162 return true;
1163}
1164
1165// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001166// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001167bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001168EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001169{
1170#if 0
1171 // ARM pseudo code...
1172 if (ConditionPassed())
1173 {
1174 EncodingSpecificOperations();
1175 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1176 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1177 if d == 15 then
1178 ALUWritePC(result); // setflags is always FALSE here
1179 else
1180 R[d] = result;
1181 if setflags then
1182 APSR.N = result<31>;
1183 APSR.Z = IsZeroBit(result);
1184 APSR.C = carry;
1185 APSR.V = overflow;
1186 }
1187#endif
1188
1189 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001190 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001191 if (!success)
1192 return false;
1193
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001194 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001195 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001196 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001197 if (!success)
1198 return false;
1199 uint32_t Rm; // the second operand
1200 switch (encoding) {
1201 case eEncodingT2:
1202 Rm = Bits32(opcode, 6, 3);
1203 break;
1204 default:
1205 return false;
1206 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001207 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001208 if (!success)
1209 return false;
1210
1211 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1212
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001213 EmulateInstruction::Context context;
1214 context.type = EmulateInstruction::eContextAdjustStackPointer;
1215 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001216
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001217 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001218 return false;
1219 }
1220 return true;
1221}
1222
Johnny Chen9b8d7832011-02-02 01:13:56 +00001223// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1224// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1225// from Thumb to ARM.
1226// BLX (immediate)
1227bool
1228EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1229{
1230#if 0
1231 // ARM pseudo code...
1232 if (ConditionPassed())
1233 {
1234 EncodingSpecificOperations();
1235 if CurrentInstrSet() == InstrSet_ARM then
1236 LR = PC - 4;
1237 else
1238 LR = PC<31:1> : '1';
1239 if targetInstrSet == InstrSet_ARM then
1240 targetAddress = Align(PC,4) + imm32;
1241 else
1242 targetAddress = PC + imm32;
1243 SelectInstrSet(targetInstrSet);
1244 BranchWritePC(targetAddress);
1245 }
1246#endif
1247
1248 bool success = false;
1249 const uint32_t opcode = OpcodeAsUnsigned (&success);
1250 if (!success)
1251 return false;
1252
1253 if (ConditionPassed())
1254 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001255 EmulateInstruction::Context context;
1256 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001257 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001258 if (!success)
1259 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001260 addr_t lr; // next instruction address
1261 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001262 int32_t imm32; // PC-relative offset
1263 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001264 case eEncodingT1:
1265 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001266 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001267 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001268 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001269 uint32_t J1 = Bit32(opcode, 13);
1270 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001271 uint32_t imm11 = Bits32(opcode, 10, 0);
1272 uint32_t I1 = !(J1 ^ S);
1273 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001274 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001275 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001276 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001277 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001278 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001279 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001280 break;
1281 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001282 case eEncodingT2:
1283 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001284 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001285 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001286 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001287 uint32_t J1 = Bit32(opcode, 13);
1288 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 uint32_t imm10L = Bits32(opcode, 10, 1);
1290 uint32_t I1 = !(J1 ^ S);
1291 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001292 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001293 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001294 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001295 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001296 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001297 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001298 break;
1299 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001300 case eEncodingA1:
1301 lr = pc + 4; // return address
1302 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001303 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001305 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001306 case eEncodingA2:
1307 lr = pc + 4; // return address
1308 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001309 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001310 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 break;
1312 default:
1313 return false;
1314 }
1315 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1316 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001317 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001318 return false;
1319 }
1320 return true;
1321}
1322
1323// Branch with Link and Exchange (register) calls a subroutine at an address and
1324// instruction set specified by a register.
1325// BLX (register)
1326bool
1327EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1328{
1329#if 0
1330 // ARM pseudo code...
1331 if (ConditionPassed())
1332 {
1333 EncodingSpecificOperations();
1334 target = R[m];
1335 if CurrentInstrSet() == InstrSet_ARM then
1336 next_instr_addr = PC - 4;
1337 LR = next_instr_addr;
1338 else
1339 next_instr_addr = PC - 2;
1340 LR = next_instr_addr<31:1> : ‘1’;
1341 BXWritePC(target);
1342 }
1343#endif
1344
1345 bool success = false;
1346 const uint32_t opcode = OpcodeAsUnsigned (&success);
1347 if (!success)
1348 return false;
1349
1350 if (ConditionPassed())
1351 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001352 EmulateInstruction::Context context;
1353 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001354 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001355 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 if (!success)
1357 return false;
1358 uint32_t Rm; // the register with the target address
1359 switch (encoding) {
1360 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001361 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001362 Rm = Bits32(opcode, 6, 3);
1363 // if m == 15 then UNPREDICTABLE;
1364 if (Rm == 15)
1365 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001366 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001367 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001368 break;
1369 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001370 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001371 Rm = Bits32(opcode, 3, 0);
1372 // if m == 15 then UNPREDICTABLE;
1373 if (Rm == 15)
1374 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001375 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 default:
1377 return false;
1378 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001380 if (!success)
1381 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001382 Register dwarf_reg;
1383 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1384 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001385 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1386 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001387 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 return false;
1389 }
1390 return true;
1391}
1392
Johnny Chenab3b3512011-02-12 00:10:51 +00001393// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001394bool
1395EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1396{
1397#if 0
1398 // ARM pseudo code...
1399 if (ConditionPassed())
1400 {
1401 EncodingSpecificOperations();
1402 BXWritePC(R[m]);
1403 }
1404#endif
1405
1406 bool success = false;
1407 const uint32_t opcode = OpcodeAsUnsigned (&success);
1408 if (!success)
1409 return false;
1410
1411 if (ConditionPassed())
1412 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 EmulateInstruction::Context context;
1414 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001415 uint32_t Rm; // the register with the target address
1416 switch (encoding) {
1417 case eEncodingT1:
1418 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001419 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001420 return false;
1421 break;
1422 case eEncodingA1:
1423 Rm = Bits32(opcode, 3, 0);
1424 break;
1425 default:
1426 return false;
1427 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001428 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001429 if (!success)
1430 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001431
1432 Register dwarf_reg;
1433 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001434 context.SetRegister (dwarf_reg);
1435 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001436 return false;
1437 }
1438 return true;
1439}
1440
Johnny Chen59e6ab72011-02-24 21:01:20 +00001441// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1442// address and instruction set specified by a register as though it were a BX instruction.
1443//
1444// TODO: Emulate Jazelle architecture?
1445// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1446bool
1447EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1448{
1449#if 0
1450 // ARM pseudo code...
1451 if (ConditionPassed())
1452 {
1453 EncodingSpecificOperations();
1454 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1455 BXWritePC(R[m]);
1456 else
1457 if JazelleAcceptsExecution() then
1458 SwitchToJazelleExecution();
1459 else
1460 SUBARCHITECTURE_DEFINED handler call;
1461 }
1462#endif
1463
1464 bool success = false;
1465 const uint32_t opcode = OpcodeAsUnsigned (&success);
1466 if (!success)
1467 return false;
1468
1469 if (ConditionPassed())
1470 {
1471 EmulateInstruction::Context context;
1472 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1473 uint32_t Rm; // the register with the target address
1474 switch (encoding) {
1475 case eEncodingT1:
1476 Rm = Bits32(opcode, 19, 16);
1477 if (BadReg(Rm))
1478 return false;
1479 if (InITBlock() && !LastInITBlock())
1480 return false;
1481 break;
1482 case eEncodingA1:
1483 Rm = Bits32(opcode, 3, 0);
1484 if (Rm == 15)
1485 return false;
1486 break;
1487 default:
1488 return false;
1489 }
1490 addr_t target = ReadCoreReg (Rm, &success);
1491 if (!success)
1492 return false;
1493
1494 Register dwarf_reg;
1495 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1496 context.SetRegister (dwarf_reg);
1497 if (!BXWritePC(context, target))
1498 return false;
1499 }
1500 return true;
1501}
1502
Johnny Chen0d0148e2011-01-28 02:26:08 +00001503// Set r7 to point to some ip offset.
1504// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001505bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001506EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001507{
1508#if 0
1509 // ARM pseudo code...
1510 if (ConditionPassed())
1511 {
1512 EncodingSpecificOperations();
1513 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1514 if d == 15 then // Can only occur for ARM encoding
1515 ALUWritePC(result); // setflags is always FALSE here
1516 else
1517 R[d] = result;
1518 if setflags then
1519 APSR.N = result<31>;
1520 APSR.Z = IsZeroBit(result);
1521 APSR.C = carry;
1522 APSR.V = overflow;
1523 }
1524#endif
1525
1526 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001527 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001528 if (!success)
1529 return false;
1530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001531 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001532 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001533 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001534 if (!success)
1535 return false;
1536 uint32_t imm32;
1537 switch (encoding) {
1538 case eEncodingA1:
1539 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1540 break;
1541 default:
1542 return false;
1543 }
1544 addr_t ip_offset = imm32;
1545 addr_t addr = ip - ip_offset; // the adjusted ip value
1546
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001547 EmulateInstruction::Context context;
1548 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1549 Register dwarf_reg;
1550 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1551 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001552
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001554 return false;
1555 }
1556 return true;
1557}
1558
1559// Set ip to point to some stack offset.
1560// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001561bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001562EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001563{
1564#if 0
1565 // ARM pseudo code...
1566 if (ConditionPassed())
1567 {
1568 EncodingSpecificOperations();
1569 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1570 if d == 15 then // Can only occur for ARM encoding
1571 ALUWritePC(result); // setflags is always FALSE here
1572 else
1573 R[d] = result;
1574 if setflags then
1575 APSR.N = result<31>;
1576 APSR.Z = IsZeroBit(result);
1577 APSR.C = carry;
1578 APSR.V = overflow;
1579 }
1580#endif
1581
1582 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001583 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001584 if (!success)
1585 return false;
1586
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001587 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001588 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001589 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001590 if (!success)
1591 return false;
1592 uint32_t imm32;
1593 switch (encoding) {
1594 case eEncodingA1:
1595 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1596 break;
1597 default:
1598 return false;
1599 }
1600 addr_t sp_offset = imm32;
1601 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1602
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001603 EmulateInstruction::Context context;
1604 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1605 Register dwarf_reg;
1606 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1607 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001608
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001609 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001610 return false;
1611 }
1612 return true;
1613}
1614
Johnny Chenc9e747f2011-02-23 01:55:07 +00001615// This instruction subtracts an immediate value from the SP value, and writes
1616// the result to the destination register.
1617//
1618// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001619bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001620EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001621{
1622#if 0
1623 // ARM pseudo code...
1624 if (ConditionPassed())
1625 {
1626 EncodingSpecificOperations();
1627 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001628 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001629 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001630 else
1631 R[d] = result;
1632 if setflags then
1633 APSR.N = result<31>;
1634 APSR.Z = IsZeroBit(result);
1635 APSR.C = carry;
1636 APSR.V = overflow;
1637 }
1638#endif
1639
1640 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001642 if (!success)
1643 return false;
1644
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001645 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001646 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001647 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001648 if (!success)
1649 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001650
1651 uint32_t Rd;
1652 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001653 uint32_t imm32;
1654 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001655 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001656 Rd = 13;
1657 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001658 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001659 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001660 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001661 Rd = Bits32(opcode, 11, 8);
1662 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001663 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001664 if (Rd == 15 && setflags)
1665 return EmulateCMPImm(eEncodingT2);
1666 if (Rd == 15 && !setflags)
1667 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001668 break;
1669 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001670 Rd = Bits32(opcode, 11, 8);
1671 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001672 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001673 if (Rd == 15)
1674 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001675 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001676 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001677 Rd = Bits32(opcode, 15, 12);
1678 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001679 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001680 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1681 // TODO: Emulate SUBS PC, LR and related instructions.
1682 if (Rd == 15 && setflags)
1683 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001684 break;
1685 default:
1686 return false;
1687 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001688 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1689
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001690 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001691 if (Rd == 13)
1692 {
1693 context.type = EmulateInstruction::eContextAdjustStackPointer;
1694 context.SetImmediateSigned (-imm32); // the stack pointer offset
1695 }
1696 else
1697 {
1698 context.type = EmulateInstruction::eContextImmediate;
1699 context.SetNoArgs ();
1700 }
1701
1702 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001703 return false;
1704 }
1705 return true;
1706}
1707
Johnny Chen08c25e82011-01-31 18:02:28 +00001708// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001709bool
1710EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001711{
1712#if 0
1713 // ARM pseudo code...
1714 if (ConditionPassed())
1715 {
1716 EncodingSpecificOperations();
1717 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1718 address = if index then offset_addr else R[n];
1719 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1720 if wback then R[n] = offset_addr;
1721 }
1722#endif
1723
1724 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001725 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001726 if (!success)
1727 return false;
1728
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001729 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001730 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001731 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001732 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001733 if (!success)
1734 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001735 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001736 uint32_t imm12;
1737 switch (encoding) {
1738 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001739 Rt = Bits32(opcode, 15, 12);
1740 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001741 break;
1742 default:
1743 return false;
1744 }
1745 addr_t sp_offset = imm12;
1746 addr_t addr = sp - sp_offset;
1747
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001748 EmulateInstruction::Context context;
1749 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1750 Register dwarf_reg;
1751 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001752 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001753 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001754 dwarf_reg.num = dwarf_r0 + Rt;
1755 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001756 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001757 if (!success)
1758 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001759 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001760 return false;
1761 }
1762 else
1763 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001764 dwarf_reg.num = dwarf_pc;
1765 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001766 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001767 if (!success)
1768 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001769 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001770 return false;
1771 }
1772
1773 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001774 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001775
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001776 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001777 return false;
1778 }
1779 return true;
1780}
1781
Johnny Chen08c25e82011-01-31 18:02:28 +00001782// Vector Push stores multiple extension registers to the stack.
1783// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001784bool
1785EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001786{
1787#if 0
1788 // ARM pseudo code...
1789 if (ConditionPassed())
1790 {
1791 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1792 address = SP - imm32;
1793 SP = SP - imm32;
1794 if single_regs then
1795 for r = 0 to regs-1
1796 MemA[address,4] = S[d+r]; address = address+4;
1797 else
1798 for r = 0 to regs-1
1799 // Store as two word-aligned words in the correct order for current endianness.
1800 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1801 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1802 address = address+8;
1803 }
1804#endif
1805
1806 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001807 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001808 if (!success)
1809 return false;
1810
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001811 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001812 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001813 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001814 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001815 if (!success)
1816 return false;
1817 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001818 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001819 uint32_t imm32; // stack offset
1820 uint32_t regs; // number of registers
1821 switch (encoding) {
1822 case eEncodingT1:
1823 case eEncodingA1:
1824 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001825 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001826 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1827 // If UInt(imm8) is odd, see "FSTMX".
1828 regs = Bits32(opcode, 7, 0) / 2;
1829 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1830 if (regs == 0 || regs > 16 || (d + regs) > 32)
1831 return false;
1832 break;
1833 case eEncodingT2:
1834 case eEncodingA2:
1835 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001836 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001837 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1838 regs = Bits32(opcode, 7, 0);
1839 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1840 if (regs == 0 || regs > 16 || (d + regs) > 32)
1841 return false;
1842 break;
1843 default:
1844 return false;
1845 }
1846 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1847 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1848 addr_t sp_offset = imm32;
1849 addr_t addr = sp - sp_offset;
1850 uint32_t i;
1851
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001852 EmulateInstruction::Context context;
1853 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1854 Register dwarf_reg;
1855 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001856 for (i=d; i<regs; ++i)
1857 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001858 dwarf_reg.num = start_reg + i;
1859 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001860 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001861 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001862 if (!success)
1863 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001864 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001865 return false;
1866 addr += reg_byte_size;
1867 }
1868
1869 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001870 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001871
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001872 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001873 return false;
1874 }
1875 return true;
1876}
1877
Johnny Chen587a0a42011-02-01 18:35:28 +00001878// Vector Pop loads multiple extension registers from the stack.
1879// It also updates SP to point just above the loaded data.
1880bool
1881EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1882{
1883#if 0
1884 // ARM pseudo code...
1885 if (ConditionPassed())
1886 {
1887 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1888 address = SP;
1889 SP = SP + imm32;
1890 if single_regs then
1891 for r = 0 to regs-1
1892 S[d+r] = MemA[address,4]; address = address+4;
1893 else
1894 for r = 0 to regs-1
1895 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1896 // Combine the word-aligned words in the correct order for current endianness.
1897 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1898 }
1899#endif
1900
1901 bool success = false;
1902 const uint32_t opcode = OpcodeAsUnsigned (&success);
1903 if (!success)
1904 return false;
1905
1906 if (ConditionPassed())
1907 {
1908 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001909 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001910 if (!success)
1911 return false;
1912 bool single_regs;
1913 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1914 uint32_t imm32; // stack offset
1915 uint32_t regs; // number of registers
1916 switch (encoding) {
1917 case eEncodingT1:
1918 case eEncodingA1:
1919 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001920 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001921 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1922 // If UInt(imm8) is odd, see "FLDMX".
1923 regs = Bits32(opcode, 7, 0) / 2;
1924 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1925 if (regs == 0 || regs > 16 || (d + regs) > 32)
1926 return false;
1927 break;
1928 case eEncodingT2:
1929 case eEncodingA2:
1930 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001931 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001932 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1933 regs = Bits32(opcode, 7, 0);
1934 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1935 if (regs == 0 || regs > 16 || (d + regs) > 32)
1936 return false;
1937 break;
1938 default:
1939 return false;
1940 }
1941 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1942 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1943 addr_t sp_offset = imm32;
1944 addr_t addr = sp;
1945 uint32_t i;
1946 uint64_t data; // uint64_t to accomodate 64-bit registers.
1947
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001948 EmulateInstruction::Context context;
1949 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1950 Register dwarf_reg;
1951 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001952 for (i=d; i<regs; ++i)
1953 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001954 dwarf_reg.num = start_reg + i;
1955 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001956 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001957 if (!success)
1958 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001959 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001960 return false;
1961 addr += reg_byte_size;
1962 }
1963
1964 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001965 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001966
1967 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1968 return false;
1969 }
1970 return true;
1971}
1972
Johnny Chenb77be412011-02-04 00:40:18 +00001973// SVC (previously SWI)
1974bool
1975EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1976{
1977#if 0
1978 // ARM pseudo code...
1979 if (ConditionPassed())
1980 {
1981 EncodingSpecificOperations();
1982 CallSupervisor();
1983 }
1984#endif
1985
1986 bool success = false;
1987 const uint32_t opcode = OpcodeAsUnsigned (&success);
1988 if (!success)
1989 return false;
1990
1991 if (ConditionPassed())
1992 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001993 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001994 addr_t lr; // next instruction address
1995 if (!success)
1996 return false;
1997 uint32_t imm32; // the immediate constant
1998 uint32_t mode; // ARM or Thumb mode
1999 switch (encoding) {
2000 case eEncodingT1:
2001 lr = (pc + 2) | 1u; // return address
2002 imm32 = Bits32(opcode, 7, 0);
2003 mode = eModeThumb;
2004 break;
2005 case eEncodingA1:
2006 lr = pc + 4; // return address
2007 imm32 = Bits32(opcode, 23, 0);
2008 mode = eModeARM;
2009 break;
2010 default:
2011 return false;
2012 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002013
2014 EmulateInstruction::Context context;
2015 context.type = EmulateInstruction::eContextSupervisorCall;
2016 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002017 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2018 return false;
2019 }
2020 return true;
2021}
2022
Johnny Chenc315f862011-02-05 00:46:10 +00002023// If Then makes up to four following instructions (the IT block) conditional.
2024bool
2025EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2026{
2027#if 0
2028 // ARM pseudo code...
2029 EncodingSpecificOperations();
2030 ITSTATE.IT<7:0> = firstcond:mask;
2031#endif
2032
2033 bool success = false;
2034 const uint32_t opcode = OpcodeAsUnsigned (&success);
2035 if (!success)
2036 return false;
2037
2038 m_it_session.InitIT(Bits32(opcode, 7, 0));
2039 return true;
2040}
2041
Johnny Chen3b620b32011-02-07 20:11:47 +00002042// Branch causes a branch to a target address.
2043bool
2044EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2045{
2046#if 0
2047 // ARM pseudo code...
2048 if (ConditionPassed())
2049 {
2050 EncodingSpecificOperations();
2051 BranchWritePC(PC + imm32);
2052 }
2053#endif
2054
2055 bool success = false;
2056 const uint32_t opcode = OpcodeAsUnsigned (&success);
2057 if (!success)
2058 return false;
2059
Johnny Chen9ee056b2011-02-08 00:06:35 +00002060 if (ConditionPassed())
2061 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002062 EmulateInstruction::Context context;
2063 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002064 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002065 if (!success)
2066 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002067 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002068 int32_t imm32; // PC-relative offset
2069 switch (encoding) {
2070 case eEncodingT1:
2071 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2072 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002073 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002074 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002075 break;
2076 case eEncodingT2:
2077 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002078 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002079 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002080 break;
2081 case eEncodingT3:
2082 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2083 {
Johnny Chenbd599902011-02-10 21:39:01 +00002084 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002085 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002086 uint32_t J1 = Bit32(opcode, 13);
2087 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002088 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002089 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002090 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002091 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002092 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002093 break;
2094 }
2095 case eEncodingT4:
2096 {
Johnny Chenbd599902011-02-10 21:39:01 +00002097 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002098 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002099 uint32_t J1 = Bit32(opcode, 13);
2100 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002101 uint32_t imm11 = Bits32(opcode, 10, 0);
2102 uint32_t I1 = !(J1 ^ S);
2103 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002104 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002105 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002106 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002107 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002108 break;
2109 }
2110 case eEncodingA1:
2111 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002112 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002113 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002114 break;
2115 default:
2116 return false;
2117 }
2118 if (!BranchWritePC(context, target))
2119 return false;
2120 }
2121 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002122}
2123
Johnny Chen53ebab72011-02-08 23:21:57 +00002124// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2125// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2126// CBNZ, CBZ
2127bool
2128EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2129{
2130#if 0
2131 // ARM pseudo code...
2132 EncodingSpecificOperations();
2133 if nonzero ^ IsZero(R[n]) then
2134 BranchWritePC(PC + imm32);
2135#endif
2136
2137 bool success = false;
2138 const uint32_t opcode = OpcodeAsUnsigned (&success);
2139 if (!success)
2140 return false;
2141
2142 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002143 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002144 if (!success)
2145 return false;
2146
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002147 EmulateInstruction::Context context;
2148 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002149 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002150 if (!success)
2151 return false;
2152
2153 addr_t target; // target address
2154 uint32_t imm32; // PC-relative offset to branch forward
2155 bool nonzero;
2156 switch (encoding) {
2157 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002158 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002159 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002160 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002161 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002162 break;
2163 default:
2164 return false;
2165 }
2166 if (nonzero ^ (reg_val == 0))
2167 if (!BranchWritePC(context, target))
2168 return false;
2169
2170 return true;
2171}
2172
Johnny Chen60299ec2011-02-17 19:34:27 +00002173// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2174// A base register provides a pointer to the table, and a second register supplies an index into the table.
2175// The branch length is twice the value of the byte returned from the table.
2176//
2177// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2178// A base register provides a pointer to the table, and a second register supplies an index into the table.
2179// The branch length is twice the value of the halfword returned from the table.
2180// TBB, TBH
2181bool
2182EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2183{
2184#if 0
2185 // ARM pseudo code...
2186 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2187 if is_tbh then
2188 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2189 else
2190 halfwords = UInt(MemU[R[n]+R[m], 1]);
2191 BranchWritePC(PC + 2*halfwords);
2192#endif
2193
2194 bool success = false;
2195 const uint32_t opcode = OpcodeAsUnsigned (&success);
2196 if (!success)
2197 return false;
2198
2199 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2200 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2201 bool is_tbh; // true if table branch halfword
2202 switch (encoding) {
2203 case eEncodingT1:
2204 Rn = Bits32(opcode, 19, 16);
2205 Rm = Bits32(opcode, 3, 0);
2206 is_tbh = BitIsSet(opcode, 4);
2207 if (Rn == 13 || BadReg(Rm))
2208 return false;
2209 if (InITBlock() && !LastInITBlock())
2210 return false;
2211 break;
2212 default:
2213 return false;
2214 }
2215
2216 // Read the address of the table from the operand register Rn.
2217 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002218 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002219 if (!success)
2220 return false;
2221
2222 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002223 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002224 if (!success)
2225 return false;
2226
2227 // the offsetted table address
2228 addr_t addr = base + (is_tbh ? index*2 : index);
2229
2230 // PC-relative offset to branch forward
2231 EmulateInstruction::Context context;
2232 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002233 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002234 if (!success)
2235 return false;
2236
Johnny Chene39f22d2011-02-19 01:36:13 +00002237 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002238 if (!success)
2239 return false;
2240
2241 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002242 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002243 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2244 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2245
2246 if (!BranchWritePC(context, target))
2247 return false;
2248
2249 return true;
2250}
2251
Johnny Chen8fa20592011-02-18 01:22:22 +00002252// This instruction adds an immediate value to a register value, and writes the result to the destination
2253// register. It can optionally update the condition flags based on the result.
2254bool
2255EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2256{
2257#if 0
2258 // ARM pseudo code...
2259 if ConditionPassed() then
2260 EncodingSpecificOperations();
2261 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2262 if d == 15 then
2263 ALUWritePC(result); // setflags is always FALSE here
2264 else
2265 R[d] = result;
2266 if setflags then
2267 APSR.N = result<31>;
2268 APSR.Z = IsZeroBit(result);
2269 APSR.C = carry;
2270 APSR.V = overflow;
2271#endif
2272
2273 bool success = false;
2274 const uint32_t opcode = OpcodeAsUnsigned (&success);
2275 if (!success)
2276 return false;
2277
2278 if (ConditionPassed())
2279 {
2280 uint32_t Rd, Rn;
2281 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2282 bool setflags;
2283 switch (encoding)
2284 {
2285 case eEncodingA1:
2286 Rd = Bits32(opcode, 15, 12);
2287 Rn = Bits32(opcode, 19, 16);
2288 setflags = BitIsSet(opcode, 20);
2289 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2290 break;
2291 default:
2292 return false;
2293 }
2294
Johnny Chen8fa20592011-02-18 01:22:22 +00002295 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002296 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002297 if (!success)
2298 return false;
2299
2300 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2301
2302 EmulateInstruction::Context context;
2303 context.type = EmulateInstruction::eContextImmediate;
2304 context.SetNoArgs ();
2305
2306 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2307 return false;
2308 }
2309 return true;
2310}
2311
Johnny Chend761dcf2011-02-17 22:03:29 +00002312// This instruction adds a register value and an optionally-shifted register value, and writes the result
2313// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002314bool
Johnny Chen9f687722011-02-18 00:02:28 +00002315EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002316{
2317#if 0
2318 // ARM pseudo code...
2319 if ConditionPassed() then
2320 EncodingSpecificOperations();
2321 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2322 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2323 if d == 15 then
2324 ALUWritePC(result); // setflags is always FALSE here
2325 else
2326 R[d] = result;
2327 if setflags then
2328 APSR.N = result<31>;
2329 APSR.Z = IsZeroBit(result);
2330 APSR.C = carry;
2331 APSR.V = overflow;
2332#endif
2333
2334 bool success = false;
2335 const uint32_t opcode = OpcodeAsUnsigned (&success);
2336 if (!success)
2337 return false;
2338
2339 if (ConditionPassed())
2340 {
2341 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002342 ARM_ShifterType shift_t;
2343 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002344 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002345 switch (encoding)
2346 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002347 case eEncodingT1:
2348 Rd = Bits32(opcode, 2, 0);
2349 Rn = Bits32(opcode, 5, 3);
2350 Rm = Bits32(opcode, 8, 6);
2351 setflags = !InITBlock();
2352 shift_t = SRType_LSL;
2353 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002354 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002355 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002356 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002357 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002358 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002359 shift_t = SRType_LSL;
2360 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002361 if (Rn == 15 && Rm == 15)
2362 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002363 if (Rd == 15 && InITBlock() && !LastInITBlock())
2364 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002365 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002366 case eEncodingA1:
2367 Rd = Bits32(opcode, 15, 12);
2368 Rn = Bits32(opcode, 19, 16);
2369 Rm = Bits32(opcode, 3, 0);
2370 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002371 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002372 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002373 default:
2374 return false;
2375 }
2376
Johnny Chen26863dc2011-02-09 23:43:29 +00002377 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002378 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002379 if (!success)
2380 return false;
2381
2382 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002383 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002384 if (!success)
2385 return false;
2386
Johnny Chene97c0d52011-02-18 19:32:20 +00002387 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002388 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002389
2390 EmulateInstruction::Context context;
2391 context.type = EmulateInstruction::eContextImmediate;
2392 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002393
Johnny Chen10530c22011-02-17 22:37:12 +00002394 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002395 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002396 }
2397 return true;
2398}
2399
Johnny Chen34075cb2011-02-22 01:56:31 +00002400// Compare Negative (immediate) adds a register value and an immediate value.
2401// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002402bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002403EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2404{
2405#if 0
2406 // ARM pseudo code...
2407 if ConditionPassed() then
2408 EncodingSpecificOperations();
2409 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2410 APSR.N = result<31>;
2411 APSR.Z = IsZeroBit(result);
2412 APSR.C = carry;
2413 APSR.V = overflow;
2414#endif
2415
2416 bool success = false;
2417 const uint32_t opcode = OpcodeAsUnsigned (&success);
2418 if (!success)
2419 return false;
2420
2421 uint32_t Rn; // the first operand
2422 uint32_t imm32; // the immediate value to be compared with
2423 switch (encoding) {
2424 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002425 Rn = Bits32(opcode, 19, 16);
2426 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2427 if (Rn == 15)
2428 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002429 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002430 case eEncodingA1:
2431 Rn = Bits32(opcode, 19, 16);
2432 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2433 break;
2434 default:
2435 return false;
2436 }
2437 // Read the register value from the operand register Rn.
2438 uint32_t reg_val = ReadCoreReg(Rn, &success);
2439 if (!success)
2440 return false;
2441
Johnny Chen078fbc62011-02-22 19:48:22 +00002442 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002443
2444 EmulateInstruction::Context context;
2445 context.type = EmulateInstruction::eContextImmediate;
2446 context.SetNoArgs ();
2447 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2448 return false;
2449
2450 return true;
2451}
2452
2453// Compare Negative (register) adds a register value and an optionally-shifted register value.
2454// It updates the condition flags based on the result, and discards the result.
2455bool
2456EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2457{
2458#if 0
2459 // ARM pseudo code...
2460 if ConditionPassed() then
2461 EncodingSpecificOperations();
2462 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2463 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2464 APSR.N = result<31>;
2465 APSR.Z = IsZeroBit(result);
2466 APSR.C = carry;
2467 APSR.V = overflow;
2468#endif
2469
2470 bool success = false;
2471 const uint32_t opcode = OpcodeAsUnsigned (&success);
2472 if (!success)
2473 return false;
2474
2475 uint32_t Rn; // the first operand
2476 uint32_t Rm; // the second operand
2477 ARM_ShifterType shift_t;
2478 uint32_t shift_n; // the shift applied to the value read from Rm
2479 switch (encoding) {
2480 case eEncodingT1:
2481 Rn = Bits32(opcode, 2, 0);
2482 Rm = Bits32(opcode, 5, 3);
2483 shift_t = SRType_LSL;
2484 shift_n = 0;
2485 break;
2486 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002487 Rn = Bits32(opcode, 19, 16);
2488 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002489 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002490 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2491 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002492 return false;
2493 break;
2494 case eEncodingA1:
2495 Rn = Bits32(opcode, 19, 16);
2496 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002497 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002498 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002499 default:
2500 return false;
2501 }
2502 // Read the register value from register Rn.
2503 uint32_t val1 = ReadCoreReg(Rn, &success);
2504 if (!success)
2505 return false;
2506
2507 // Read the register value from register Rm.
2508 uint32_t val2 = ReadCoreReg(Rm, &success);
2509 if (!success)
2510 return false;
2511
2512 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002513 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002514
2515 EmulateInstruction::Context context;
2516 context.type = EmulateInstruction::eContextImmediate;
2517 context.SetNoArgs();
2518 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2519 return false;
2520
2521 return true;
2522}
2523
2524// Compare (immediate) subtracts an immediate value from a register value.
2525// It updates the condition flags based on the result, and discards the result.
2526bool
2527EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002528{
2529#if 0
2530 // ARM pseudo code...
2531 if ConditionPassed() then
2532 EncodingSpecificOperations();
2533 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2534 APSR.N = result<31>;
2535 APSR.Z = IsZeroBit(result);
2536 APSR.C = carry;
2537 APSR.V = overflow;
2538#endif
2539
2540 bool success = false;
2541 const uint32_t opcode = OpcodeAsUnsigned (&success);
2542 if (!success)
2543 return false;
2544
2545 uint32_t Rn; // the first operand
2546 uint32_t imm32; // the immediate value to be compared with
2547 switch (encoding) {
2548 case eEncodingT1:
2549 Rn = Bits32(opcode, 10, 8);
2550 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002551 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002552 case eEncodingT2:
2553 Rn = Bits32(opcode, 19, 16);
2554 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2555 if (Rn == 15)
2556 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002557 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002558 case eEncodingA1:
2559 Rn = Bits32(opcode, 19, 16);
2560 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002561 break;
2562 default:
2563 return false;
2564 }
2565 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002566 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002567 if (!success)
2568 return false;
2569
Johnny Chen10530c22011-02-17 22:37:12 +00002570 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2571
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002572 EmulateInstruction::Context context;
2573 context.type = EmulateInstruction::eContextImmediate;
2574 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002575 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2576 return false;
2577
Johnny Chend4dc4442011-02-11 02:02:56 +00002578 return true;
2579}
2580
Johnny Chen34075cb2011-02-22 01:56:31 +00002581// Compare (register) subtracts an optionally-shifted register value from a register value.
2582// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002583bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002584EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002585{
2586#if 0
2587 // ARM pseudo code...
2588 if ConditionPassed() then
2589 EncodingSpecificOperations();
2590 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2591 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2592 APSR.N = result<31>;
2593 APSR.Z = IsZeroBit(result);
2594 APSR.C = carry;
2595 APSR.V = overflow;
2596#endif
2597
2598 bool success = false;
2599 const uint32_t opcode = OpcodeAsUnsigned (&success);
2600 if (!success)
2601 return false;
2602
2603 uint32_t Rn; // the first operand
2604 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002605 ARM_ShifterType shift_t;
2606 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002607 switch (encoding) {
2608 case eEncodingT1:
2609 Rn = Bits32(opcode, 2, 0);
2610 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002611 shift_t = SRType_LSL;
2612 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002613 break;
2614 case eEncodingT2:
2615 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2616 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002617 shift_t = SRType_LSL;
2618 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002619 if (Rn < 8 && Rm < 8)
2620 return false;
2621 if (Rn == 15 || Rm == 15)
2622 return false;
2623 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002624 case eEncodingA1:
2625 Rn = Bits32(opcode, 19, 16);
2626 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002627 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002628 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002629 default:
2630 return false;
2631 }
2632 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002633 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002634 if (!success)
2635 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002636
Johnny Chene4a4d302011-02-11 21:53:58 +00002637 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002638 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002639 if (!success)
2640 return false;
2641
Johnny Chen34075cb2011-02-22 01:56:31 +00002642 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2643 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002644
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002645 EmulateInstruction::Context context;
2646 context.type = EmulateInstruction::eContextImmediate;
2647 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002648 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2649 return false;
2650
Johnny Chene4a4d302011-02-11 21:53:58 +00002651 return true;
2652}
2653
Johnny Chen82f16aa2011-02-15 20:10:55 +00002654// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2655// shifting in copies of its sign bit, and writes the result to the destination register. It can
2656// optionally update the condition flags based on the result.
2657bool
2658EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2659{
2660#if 0
2661 // ARM pseudo code...
2662 if ConditionPassed() then
2663 EncodingSpecificOperations();
2664 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2665 if d == 15 then // Can only occur for ARM encoding
2666 ALUWritePC(result); // setflags is always FALSE here
2667 else
2668 R[d] = result;
2669 if setflags then
2670 APSR.N = result<31>;
2671 APSR.Z = IsZeroBit(result);
2672 APSR.C = carry;
2673 // APSR.V unchanged
2674#endif
2675
Johnny Chen41a0a152011-02-16 01:27:54 +00002676 return EmulateShiftImm(encoding, SRType_ASR);
2677}
2678
2679// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2680// shifting in copies of its sign bit, and writes the result to the destination register.
2681// The variable number of bits is read from the bottom byte of a register. It can optionally update
2682// the condition flags based on the result.
2683bool
2684EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2685{
2686#if 0
2687 // ARM pseudo code...
2688 if ConditionPassed() then
2689 EncodingSpecificOperations();
2690 shift_n = UInt(R[m]<7:0>);
2691 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2692 R[d] = result;
2693 if setflags then
2694 APSR.N = result<31>;
2695 APSR.Z = IsZeroBit(result);
2696 APSR.C = carry;
2697 // APSR.V unchanged
2698#endif
2699
2700 return EmulateShiftReg(encoding, SRType_ASR);
2701}
2702
2703// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2704// shifting in zeros, and writes the result to the destination register. It can optionally
2705// update the condition flags based on the result.
2706bool
2707EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2708{
2709#if 0
2710 // ARM pseudo code...
2711 if ConditionPassed() then
2712 EncodingSpecificOperations();
2713 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2714 if d == 15 then // Can only occur for ARM encoding
2715 ALUWritePC(result); // setflags is always FALSE here
2716 else
2717 R[d] = result;
2718 if setflags then
2719 APSR.N = result<31>;
2720 APSR.Z = IsZeroBit(result);
2721 APSR.C = carry;
2722 // APSR.V unchanged
2723#endif
2724
2725 return EmulateShiftImm(encoding, SRType_LSL);
2726}
2727
2728// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2729// shifting in zeros, and writes the result to the destination register. The variable number
2730// of bits is read from the bottom byte of a register. It can optionally update the condition
2731// flags based on the result.
2732bool
2733EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2734{
2735#if 0
2736 // ARM pseudo code...
2737 if ConditionPassed() then
2738 EncodingSpecificOperations();
2739 shift_n = UInt(R[m]<7:0>);
2740 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2741 R[d] = result;
2742 if setflags then
2743 APSR.N = result<31>;
2744 APSR.Z = IsZeroBit(result);
2745 APSR.C = carry;
2746 // APSR.V unchanged
2747#endif
2748
2749 return EmulateShiftReg(encoding, SRType_LSL);
2750}
2751
2752// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2753// shifting in zeros, and writes the result to the destination register. It can optionally
2754// update the condition flags based on the result.
2755bool
2756EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2757{
2758#if 0
2759 // ARM pseudo code...
2760 if ConditionPassed() then
2761 EncodingSpecificOperations();
2762 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2763 if d == 15 then // Can only occur for ARM encoding
2764 ALUWritePC(result); // setflags is always FALSE here
2765 else
2766 R[d] = result;
2767 if setflags then
2768 APSR.N = result<31>;
2769 APSR.Z = IsZeroBit(result);
2770 APSR.C = carry;
2771 // APSR.V unchanged
2772#endif
2773
2774 return EmulateShiftImm(encoding, SRType_LSR);
2775}
2776
2777// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2778// shifting in zeros, and writes the result to the destination register. The variable number
2779// of bits is read from the bottom byte of a register. It can optionally update the condition
2780// flags based on the result.
2781bool
2782EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2783{
2784#if 0
2785 // ARM pseudo code...
2786 if ConditionPassed() then
2787 EncodingSpecificOperations();
2788 shift_n = UInt(R[m]<7:0>);
2789 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2790 R[d] = result;
2791 if setflags then
2792 APSR.N = result<31>;
2793 APSR.Z = IsZeroBit(result);
2794 APSR.C = carry;
2795 // APSR.V unchanged
2796#endif
2797
2798 return EmulateShiftReg(encoding, SRType_LSR);
2799}
2800
Johnny Cheneeab4852011-02-16 22:14:44 +00002801// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2802// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2803// It can optionally update the condition flags based on the result.
2804bool
2805EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2806{
2807#if 0
2808 // ARM pseudo code...
2809 if ConditionPassed() then
2810 EncodingSpecificOperations();
2811 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2812 if d == 15 then // Can only occur for ARM encoding
2813 ALUWritePC(result); // setflags is always FALSE here
2814 else
2815 R[d] = result;
2816 if setflags then
2817 APSR.N = result<31>;
2818 APSR.Z = IsZeroBit(result);
2819 APSR.C = carry;
2820 // APSR.V unchanged
2821#endif
2822
2823 return EmulateShiftImm(encoding, SRType_ROR);
2824}
2825
2826// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2827// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2828// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2829// flags based on the result.
2830bool
2831EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2832{
2833#if 0
2834 // ARM pseudo code...
2835 if ConditionPassed() then
2836 EncodingSpecificOperations();
2837 shift_n = UInt(R[m]<7:0>);
2838 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2839 R[d] = result;
2840 if setflags then
2841 APSR.N = result<31>;
2842 APSR.Z = IsZeroBit(result);
2843 APSR.C = carry;
2844 // APSR.V unchanged
2845#endif
2846
2847 return EmulateShiftReg(encoding, SRType_ROR);
2848}
2849
2850// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2851// with the carry flag shifted into bit [31].
2852//
2853// RRX can optionally update the condition flags based on the result.
2854// In that case, bit [0] is shifted into the carry flag.
2855bool
2856EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2857{
2858#if 0
2859 // ARM pseudo code...
2860 if ConditionPassed() then
2861 EncodingSpecificOperations();
2862 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2863 if d == 15 then // Can only occur for ARM encoding
2864 ALUWritePC(result); // setflags is always FALSE here
2865 else
2866 R[d] = result;
2867 if setflags then
2868 APSR.N = result<31>;
2869 APSR.Z = IsZeroBit(result);
2870 APSR.C = carry;
2871 // APSR.V unchanged
2872#endif
2873
2874 return EmulateShiftImm(encoding, SRType_RRX);
2875}
2876
Johnny Chen41a0a152011-02-16 01:27:54 +00002877bool
2878EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2879{
2880 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2881
Johnny Chen82f16aa2011-02-15 20:10:55 +00002882 bool success = false;
2883 const uint32_t opcode = OpcodeAsUnsigned (&success);
2884 if (!success)
2885 return false;
2886
2887 if (ConditionPassed())
2888 {
Johnny Chene7f89532011-02-15 23:22:46 +00002889 uint32_t Rd; // the destination register
2890 uint32_t Rm; // the first operand register
2891 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002892 uint32_t carry; // the carry bit after the shift operation
2893 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002894
2895 // Special case handling!
2896 // A8.6.139 ROR (immediate) -- Encoding T1
2897 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2898 {
2899 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2900 // have the same decoding of bit fields as the other Thumb2 shift operations.
2901 encoding = eEncodingT2;
2902 }
2903
Johnny Chen82f16aa2011-02-15 20:10:55 +00002904 switch (encoding) {
2905 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002906 // Due to the above special case handling!
2907 assert(shift_type != SRType_ROR);
2908
Johnny Chen82f16aa2011-02-15 20:10:55 +00002909 Rd = Bits32(opcode, 2, 0);
2910 Rm = Bits32(opcode, 5, 3);
2911 setflags = !InITBlock();
2912 imm5 = Bits32(opcode, 10, 6);
2913 break;
2914 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002915 // A8.6.141 RRX
2916 assert(shift_type != SRType_RRX);
2917
Johnny Chen82f16aa2011-02-15 20:10:55 +00002918 Rd = Bits32(opcode, 11, 8);
2919 Rm = Bits32(opcode, 3, 0);
2920 setflags = BitIsSet(opcode, 20);
2921 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2922 if (BadReg(Rd) || BadReg(Rm))
2923 return false;
2924 break;
2925 case eEncodingA1:
2926 Rd = Bits32(opcode, 15, 12);
2927 Rm = Bits32(opcode, 3, 0);
2928 setflags = BitIsSet(opcode, 20);
2929 imm5 = Bits32(opcode, 11, 7);
2930 break;
2931 default:
2932 return false;
2933 }
2934
Johnny Cheneeab4852011-02-16 22:14:44 +00002935 // A8.6.139 ROR (immediate)
2936 if (shift_type == SRType_ROR && imm5 == 0)
2937 shift_type = SRType_RRX;
2938
Johnny Chen82f16aa2011-02-15 20:10:55 +00002939 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002940 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002941 if (!success)
2942 return false;
2943
Johnny Cheneeab4852011-02-16 22:14:44 +00002944 // Decode the shift amount if not RRX.
2945 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002946
Johnny Chene97c0d52011-02-18 19:32:20 +00002947 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002948
2949 // The context specifies that an immediate is to be moved into Rd.
2950 EmulateInstruction::Context context;
2951 context.type = EmulateInstruction::eContextImmediate;
2952 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002953
Johnny Chen10530c22011-02-17 22:37:12 +00002954 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002955 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002956 }
2957 return true;
2958}
2959
Johnny Chene7f89532011-02-15 23:22:46 +00002960bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002961EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002962{
Johnny Chen41a0a152011-02-16 01:27:54 +00002963 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002964
2965 bool success = false;
2966 const uint32_t opcode = OpcodeAsUnsigned (&success);
2967 if (!success)
2968 return false;
2969
2970 if (ConditionPassed())
2971 {
2972 uint32_t Rd; // the destination register
2973 uint32_t Rn; // the first operand register
2974 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2975 uint32_t carry; // the carry bit after the shift operation
2976 bool setflags;
2977 switch (encoding) {
2978 case eEncodingT1:
2979 Rd = Bits32(opcode, 2, 0);
2980 Rn = Rd;
2981 Rm = Bits32(opcode, 5, 3);
2982 setflags = !InITBlock();
2983 break;
2984 case eEncodingT2:
2985 Rd = Bits32(opcode, 11, 8);
2986 Rn = Bits32(opcode, 19, 16);
2987 Rm = Bits32(opcode, 3, 0);
2988 setflags = BitIsSet(opcode, 20);
2989 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2990 return false;
2991 break;
2992 case eEncodingA1:
2993 Rd = Bits32(opcode, 15, 12);
2994 Rn = Bits32(opcode, 3, 0);
2995 Rm = Bits32(opcode, 11, 8);
2996 setflags = BitIsSet(opcode, 20);
2997 if (Rd == 15 || Rn == 15 || Rm == 15)
2998 return false;
2999 break;
3000 default:
3001 return false;
3002 }
3003
3004 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003005 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003006 if (!success)
3007 return false;
3008 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003009 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003010 if (!success)
3011 return false;
3012
3013 // Get the shift amount.
3014 uint32_t amt = Bits32(val, 7, 0);
3015
Johnny Chene97c0d52011-02-18 19:32:20 +00003016 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003017
3018 // The context specifies that an immediate is to be moved into Rd.
3019 EmulateInstruction::Context context;
3020 context.type = EmulateInstruction::eContextImmediate;
3021 context.SetNoArgs ();
3022
Johnny Chen10530c22011-02-17 22:37:12 +00003023 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003024 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003025 }
3026 return true;
3027}
3028
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003029// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003030// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003031// can be written back to the base register.
3032bool
3033EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3034{
3035#if 0
3036 // ARM pseudo code...
3037 if ConditionPassed()
3038 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3039 address = R[n];
3040
3041 for i = 0 to 14
3042 if registers<i> == '1' then
3043 R[i] = MemA[address, 4]; address = address + 4;
3044 if registers<15> == '1' then
3045 LoadWritePC (MemA[address, 4]);
3046
3047 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3048 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3049
3050#endif
3051
3052 bool success = false;
3053 const uint32_t opcode = OpcodeAsUnsigned (&success);
3054 if (!success)
3055 return false;
3056
3057 if (ConditionPassed())
3058 {
3059 uint32_t n;
3060 uint32_t registers = 0;
3061 bool wback;
3062 const uint32_t addr_byte_size = GetAddressByteSize();
3063 switch (encoding)
3064 {
3065 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003066 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003067 n = Bits32 (opcode, 10, 8);
3068 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003069 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003070 wback = BitIsClear (registers, n);
3071 // if BitCount(registers) < 1 then UNPREDICTABLE;
3072 if (BitCount(registers) < 1)
3073 return false;
3074 break;
3075 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003076 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3077 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003078 n = Bits32 (opcode, 19, 16);
3079 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003080 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003081 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003082
3083 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003084 if ((n == 15)
3085 || (BitCount (registers) < 2)
3086 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3087 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003088
3089 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003090 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003091 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003092
3093 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003094 if (wback
3095 && BitIsSet (registers, n))
3096 return false;
3097 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003098
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003099 case eEncodingA1:
3100 n = Bits32 (opcode, 19, 16);
3101 registers = Bits32 (opcode, 15, 0);
3102 wback = BitIsSet (opcode, 21);
3103 if ((n == 15)
3104 || (BitCount (registers) < 1))
3105 return false;
3106 break;
3107 default:
3108 return false;
3109 }
3110
3111 int32_t offset = 0;
3112 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3113 if (!success)
3114 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003115
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003116 EmulateInstruction::Context context;
3117 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3118 Register dwarf_reg;
3119 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3120 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003121
3122 for (int i = 0; i < 14; ++i)
3123 {
3124 if (BitIsSet (registers, i))
3125 {
Caroline Tice85aab332011-02-08 23:56:10 +00003126 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003127 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003128 if (wback && (n == 13)) // Pop Instruction
3129 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3130
3131 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003132 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003133 if (!success)
3134 return false;
3135
3136 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3137 return false;
3138
3139 offset += addr_byte_size;
3140 }
3141 }
3142
3143 if (BitIsSet (registers, 15))
3144 {
3145 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003146 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003147 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003148 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003149 if (!success)
3150 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003151 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003152 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003153 return false;
3154 }
3155
3156 if (wback && BitIsClear (registers, n))
3157 {
Caroline Ticefa172202011-02-11 22:49:54 +00003158 // R[n] = R[n] + 4 * BitCount (registers)
3159 int32_t offset = addr_byte_size * BitCount (registers);
3160 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003161 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003162
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003163 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3164 return false;
3165 }
3166 if (wback && BitIsSet (registers, n))
3167 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003168 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003169 }
3170 return true;
3171}
Caroline Tice713c2662011-02-11 17:59:55 +00003172
3173// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3174// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3175// can optionally be written back tot he base registers.
3176bool
3177EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3178{
3179#if 0
3180 // ARM pseudo code...
3181 if ConditionPassed() then
3182 EncodingSpecificOperations();
3183 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003184
Caroline Tice713c2662011-02-11 17:59:55 +00003185 for i = 0 to 14
3186 if registers<i> == ’1’ then
3187 R[i] = MemA[address,4]; address = address + 4;
3188
3189 if registers<15> == ’1’ then
3190 LoadWritePC(MemA[address,4]);
3191
3192 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3193 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3194#endif
3195
3196 bool success = false;
3197 const uint32_t opcode = OpcodeAsUnsigned (&success);
3198 if (!success)
3199 return false;
3200
3201 if (ConditionPassed())
3202 {
3203 uint32_t n;
3204 uint32_t registers = 0;
3205 bool wback;
3206 const uint32_t addr_byte_size = GetAddressByteSize();
3207
3208 // EncodingSpecificOperations();
3209 switch (encoding)
3210 {
3211 case eEncodingA1:
3212 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3213 n = Bits32 (opcode, 19, 16);
3214 registers = Bits32 (opcode, 15, 0);
3215 wback = BitIsSet (opcode, 21);
3216
3217 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3218 if ((n == 15) || (BitCount (registers) < 1))
3219 return false;
3220
3221 break;
3222
3223 default:
3224 return false;
3225 }
3226 // address = R[n] - 4*BitCount(registers) + 4;
3227
3228 int32_t offset = 0;
3229 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3230
3231 if (!success)
3232 return false;
3233
3234 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3235
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003236 EmulateInstruction::Context context;
3237 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3238 Register dwarf_reg;
3239 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3240 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003241
3242 // for i = 0 to 14
3243 for (int i = 0; i < 14; ++i)
3244 {
3245 // if registers<i> == ’1’ then
3246 if (BitIsSet (registers, i))
3247 {
3248 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003249 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003250 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003251 if (!success)
3252 return false;
3253 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3254 return false;
3255 offset += addr_byte_size;
3256 }
3257 }
3258
3259 // if registers<15> == ’1’ then
3260 // LoadWritePC(MemA[address,4]);
3261 if (BitIsSet (registers, 15))
3262 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003263 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003264 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003265 if (!success)
3266 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003267 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003268 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003269 return false;
3270 }
3271
3272 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3273 if (wback && BitIsClear (registers, n))
3274 {
Caroline Tice713c2662011-02-11 17:59:55 +00003275 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3276 if (!success)
3277 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003278
3279 offset = (addr_byte_size * BitCount (registers)) * -1;
3280 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003281 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003282 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003283 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3284 return false;
3285 }
3286
3287 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3288 if (wback && BitIsSet (registers, n))
3289 return WriteBits32Unknown (n);
3290 }
3291 return true;
3292}
3293
3294// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3295// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3296// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003297bool
3298EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3299{
3300#if 0
3301 // ARM pseudo code...
3302 if ConditionPassed() then
3303 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3304 address = R[n] - 4*BitCount(registers);
3305
3306 for i = 0 to 14
3307 if registers<i> == ’1’ then
3308 R[i] = MemA[address,4]; address = address + 4;
3309 if registers<15> == ’1’ then
3310 LoadWritePC(MemA[address,4]);
3311
3312 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3313 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3314#endif
3315
3316 bool success = false;
3317 const uint32_t opcode = OpcodeAsUnsigned (&success);
3318 if (!success)
3319 return false;
3320
3321 if (ConditionPassed())
3322 {
3323 uint32_t n;
3324 uint32_t registers = 0;
3325 bool wback;
3326 const uint32_t addr_byte_size = GetAddressByteSize();
3327 switch (encoding)
3328 {
3329 case eEncodingT1:
3330 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3331 n = Bits32 (opcode, 19, 16);
3332 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003333 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003334 wback = BitIsSet (opcode, 21);
3335
3336 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3337 if ((n == 15)
3338 || (BitCount (registers) < 2)
3339 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3340 return false;
3341
3342 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003343 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003344 return false;
3345
3346 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3347 if (wback && BitIsSet (registers, n))
3348 return false;
3349
3350 break;
3351
3352 case eEncodingA1:
3353 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3354 n = Bits32 (opcode, 19, 16);
3355 registers = Bits32 (opcode, 15, 0);
3356 wback = BitIsSet (opcode, 21);
3357
3358 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3359 if ((n == 15) || (BitCount (registers) < 1))
3360 return false;
3361
3362 break;
3363
3364 default:
3365 return false;
3366 }
3367
Caroline Tice713c2662011-02-11 17:59:55 +00003368 // address = R[n] - 4*BitCount(registers);
3369
Caroline Tice0b29e242011-02-08 23:16:02 +00003370 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003371 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3372
3373 if (!success)
3374 return false;
3375
3376 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003377 EmulateInstruction::Context context;
3378 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3379 Register dwarf_reg;
3380 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3381 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003382
3383 for (int i = 0; i < 14; ++i)
3384 {
3385 if (BitIsSet (registers, i))
3386 {
3387 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003388 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003389 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003390 if (!success)
3391 return false;
3392
3393 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3394 return false;
3395
3396 offset += addr_byte_size;
3397 }
3398 }
3399
3400 // if registers<15> == ’1’ then
3401 // LoadWritePC(MemA[address,4]);
3402 if (BitIsSet (registers, 15))
3403 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003404 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003405 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003406 if (!success)
3407 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003408 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003409 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003410 return false;
3411 }
3412
3413 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3414 if (wback && BitIsClear (registers, n))
3415 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003416 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3417 if (!success)
3418 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003419
3420 offset = (addr_byte_size * BitCount (registers)) * -1;
3421 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003422 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003423 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3425 return false;
3426 }
3427
3428 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3429 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003430 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003431 }
3432 return true;
3433}
Caroline Tice85aab332011-02-08 23:56:10 +00003434
Caroline Tice713c2662011-02-11 17:59:55 +00003435// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3436// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3437// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003438bool
3439EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3440{
3441#if 0
3442 if ConditionPassed() then
3443 EncodingSpecificOperations();
3444 address = R[n] + 4;
3445
3446 for i = 0 to 14
3447 if registers<i> == ’1’ then
3448 R[i] = MemA[address,4]; address = address + 4;
3449 if registers<15> == ’1’ then
3450 LoadWritePC(MemA[address,4]);
3451
3452 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3453 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3454#endif
3455
3456 bool success = false;
3457 const uint32_t opcode = OpcodeAsUnsigned (&success);
3458 if (!success)
3459 return false;
3460
3461 if (ConditionPassed())
3462 {
3463 uint32_t n;
3464 uint32_t registers = 0;
3465 bool wback;
3466 const uint32_t addr_byte_size = GetAddressByteSize();
3467 switch (encoding)
3468 {
3469 case eEncodingA1:
3470 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3471 n = Bits32 (opcode, 19, 16);
3472 registers = Bits32 (opcode, 15, 0);
3473 wback = BitIsSet (opcode, 21);
3474
3475 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3476 if ((n == 15) || (BitCount (registers) < 1))
3477 return false;
3478
3479 break;
3480 default:
3481 return false;
3482 }
3483 // address = R[n] + 4;
3484
3485 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003486 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3487
3488 if (!success)
3489 return false;
3490
3491 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003492
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003493 EmulateInstruction::Context context;
3494 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3495 Register dwarf_reg;
3496 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3497 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003498
3499 for (int i = 0; i < 14; ++i)
3500 {
3501 if (BitIsSet (registers, i))
3502 {
3503 // R[i] = MemA[address,4]; address = address + 4;
3504
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003505 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003506 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003507 if (!success)
3508 return false;
3509
3510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3511 return false;
3512
3513 offset += addr_byte_size;
3514 }
3515 }
3516
3517 // if registers<15> == ’1’ then
3518 // LoadWritePC(MemA[address,4]);
3519 if (BitIsSet (registers, 15))
3520 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003521 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003522 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003523 if (!success)
3524 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003525 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003526 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003527 return false;
3528 }
3529
3530 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3531 if (wback && BitIsClear (registers, n))
3532 {
Caroline Tice85aab332011-02-08 23:56:10 +00003533 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3534 if (!success)
3535 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003536
3537 offset = addr_byte_size * BitCount (registers);
3538 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003539 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003540 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003541 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3542 return false;
3543 }
3544
3545 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3546 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003547 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003548 }
3549 return true;
3550}
Caroline Tice0b29e242011-02-08 23:16:02 +00003551
Johnny Chenef21b592011-02-10 01:52:38 +00003552// Load Register (immediate) calculates an address from a base register value and
3553// an immediate offset, loads a word from memory, and writes to a register.
3554// LDR (immediate, Thumb)
3555bool
3556EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3557{
3558#if 0
3559 // ARM pseudo code...
3560 if (ConditionPassed())
3561 {
3562 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3563 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3564 address = if index then offset_addr else R[n];
3565 data = MemU[address,4];
3566 if wback then R[n] = offset_addr;
3567 if t == 15 then
3568 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3569 elsif UnalignedSupport() || address<1:0> = '00' then
3570 R[t] = data;
3571 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3572 }
3573#endif
3574
3575 bool success = false;
3576 const uint32_t opcode = OpcodeAsUnsigned (&success);
3577 if (!success)
3578 return false;
3579
3580 if (ConditionPassed())
3581 {
3582 uint32_t Rt; // the destination register
3583 uint32_t Rn; // the base register
3584 uint32_t imm32; // the immediate offset used to form the address
3585 addr_t offset_addr; // the offset address
3586 addr_t address; // the calculated address
3587 uint32_t data; // the literal data value from memory load
3588 bool add, index, wback;
3589 switch (encoding) {
3590 case eEncodingT1:
3591 Rt = Bits32(opcode, 5, 3);
3592 Rn = Bits32(opcode, 2, 0);
3593 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3594 // index = TRUE; add = TRUE; wback = FALSE
3595 add = true;
3596 index = true;
3597 wback = false;
3598 break;
3599 default:
3600 return false;
3601 }
3602 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3603 if (!success)
3604 return false;
3605 if (add)
3606 offset_addr = base + imm32;
3607 else
3608 offset_addr = base - imm32;
3609
3610 address = (index ? offset_addr : base);
3611
3612 if (wback)
3613 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003614 EmulateInstruction::Context ctx;
3615 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3616 Register dwarf_reg;
3617 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3618 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3619
Johnny Chenef21b592011-02-10 01:52:38 +00003620 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3621 return false;
3622 }
3623
3624 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003625 EmulateInstruction::Context context;
3626 context.type = EmulateInstruction::eContextImmediate;
3627 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003628
3629 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003630 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003631 if (!success)
3632 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003633
3634 if (Rt == 15)
3635 {
3636 if (Bits32(address, 1, 0) == 0)
3637 {
Johnny Chen668b4512011-02-15 21:08:58 +00003638 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003639 return false;
3640 }
3641 else
3642 return false;
3643 }
3644 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3645 {
3646 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3647 return false;
3648 }
3649 else
3650 return false;
3651 }
3652 return true;
3653}
3654
Caroline Ticeaf556562011-02-15 18:42:15 +00003655// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3656// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3657// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003658bool
3659EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3660{
3661#if 0
3662 if ConditionPassed() then
3663 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3664 address = R[n];
3665
3666 for i = 0 to 14
3667 if registers<i> == ’1’ then
3668 if i == n && wback && i != LowestSetBit(registers) then
3669 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3670 else
3671 MemA[address,4] = R[i];
3672 address = address + 4;
3673
3674 if registers<15> == ’1’ then // Only possible for encoding A1
3675 MemA[address,4] = PCStoreValue();
3676 if wback then R[n] = R[n] + 4*BitCount(registers);
3677#endif
3678
3679 bool success = false;
3680 const uint32_t opcode = OpcodeAsUnsigned (&success);
3681 if (!success)
3682 return false;
3683
3684 if (ConditionPassed ())
3685 {
3686 uint32_t n;
3687 uint32_t registers = 0;
3688 bool wback;
3689 const uint32_t addr_byte_size = GetAddressByteSize();
3690
3691 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3692 switch (encoding)
3693 {
3694 case eEncodingT1:
3695 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3696 n = Bits32 (opcode, 10, 8);
3697 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003698 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003699 wback = true;
3700
3701 // if BitCount(registers) < 1 then UNPREDICTABLE;
3702 if (BitCount (registers) < 1)
3703 return false;
3704
3705 break;
3706
3707 case eEncodingT2:
3708 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3709 n = Bits32 (opcode, 19, 16);
3710 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003711 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003712 wback = BitIsSet (opcode, 21);
3713
3714 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3715 if ((n == 15) || (BitCount (registers) < 2))
3716 return false;
3717
3718 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3719 if (wback && BitIsSet (registers, n))
3720 return false;
3721
3722 break;
3723
3724 case eEncodingA1:
3725 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3726 n = Bits32 (opcode, 19, 16);
3727 registers = Bits32 (opcode, 15, 0);
3728 wback = BitIsSet (opcode, 21);
3729
3730 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3731 if ((n == 15) || (BitCount (registers) < 1))
3732 return false;
3733
3734 break;
3735
3736 default:
3737 return false;
3738 }
3739
3740 // address = R[n];
3741 int32_t offset = 0;
3742 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3743 if (!success)
3744 return false;
3745
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003746 EmulateInstruction::Context context;
3747 context.type = EmulateInstruction::eContextRegisterStore;
3748 Register base_reg;
3749 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003750
3751 // for i = 0 to 14
3752 for (int i = 0; i < 14; ++i)
3753 {
3754 int lowest_set_bit = 14;
3755 // if registers<i> == ’1’ then
3756 if (BitIsSet (registers, i))
3757 {
3758 if (i < lowest_set_bit)
3759 lowest_set_bit = i;
3760 // if i == n && wback && i != LowestSetBit(registers) then
3761 if ((i == n) && wback && (i != lowest_set_bit))
3762 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3763 WriteBits32UnknownToMemory (address + offset);
3764 else
3765 {
3766 // MemA[address,4] = R[i];
3767 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3768 if (!success)
3769 return false;
3770
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003771 Register data_reg;
3772 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3773 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003774 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003775 return false;
3776 }
3777
3778 // address = address + 4;
3779 offset += addr_byte_size;
3780 }
3781 }
3782
3783 // if registers<15> == ’1’ then // Only possible for encoding A1
3784 // MemA[address,4] = PCStoreValue();
3785 if (BitIsSet (registers, 15))
3786 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003787 Register pc_reg;
3788 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3789 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003790 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3791 if (!success)
3792 return false;
3793
Caroline Ticecc96eb52011-02-17 19:20:40 +00003794 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003795 return false;
3796 }
3797
3798 // if wback then R[n] = R[n] + 4*BitCount(registers);
3799 if (wback)
3800 {
3801 offset = addr_byte_size * BitCount (registers);
3802 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003803 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003804 addr_t data = address + offset;
3805 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3806 return false;
3807 }
3808 }
3809 return true;
3810}
3811
Caroline Ticeaf556562011-02-15 18:42:15 +00003812// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3813// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3814// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003815bool
3816EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3817{
3818#if 0
3819 if ConditionPassed() then
3820 EncodingSpecificOperations();
3821 address = R[n] - 4*BitCount(registers) + 4;
3822
3823 for i = 0 to 14
3824 if registers<i> == ’1’ then
3825 if i == n && wback && i != LowestSetBit(registers) then
3826 MemA[address,4] = bits(32) UNKNOWN;
3827 else
3828 MemA[address,4] = R[i];
3829 address = address + 4;
3830
3831 if registers<15> == ’1’ then
3832 MemA[address,4] = PCStoreValue();
3833
3834 if wback then R[n] = R[n] - 4*BitCount(registers);
3835#endif
3836
3837 bool success = false;
3838 const uint32_t opcode = OpcodeAsUnsigned (&success);
3839 if (!success)
3840 return false;
3841
3842 if (ConditionPassed ())
3843 {
3844 uint32_t n;
3845 uint32_t registers = 0;
3846 bool wback;
3847 const uint32_t addr_byte_size = GetAddressByteSize();
3848
3849 // EncodingSpecificOperations();
3850 switch (encoding)
3851 {
3852 case eEncodingA1:
3853 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3854 n = Bits32 (opcode, 19, 16);
3855 registers = Bits32 (opcode, 15, 0);
3856 wback = BitIsSet (opcode, 21);
3857
3858 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3859 if ((n == 15) || (BitCount (registers) < 1))
3860 return false;
3861 break;
3862 default:
3863 return false;
3864 }
3865
3866 // address = R[n] - 4*BitCount(registers) + 4;
3867 int32_t offset = 0;
3868 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3869 if (!success)
3870 return false;
3871
3872 address = address - (addr_byte_size * BitCount (registers)) + 4;
3873
3874 EmulateInstruction::Context context;
3875 context.type = EmulateInstruction::eContextRegisterStore;
3876 Register base_reg;
3877 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3878
3879 // for i = 0 to 14
3880 for (int i = 0; i < 14; ++i)
3881 {
3882 int lowest_bit_set = 14;
3883 // if registers<i> == ’1’ then
3884 if (BitIsSet (registers, i))
3885 {
3886 if (i < lowest_bit_set)
3887 lowest_bit_set = i;
3888 //if i == n && wback && i != LowestSetBit(registers) then
3889 if ((i == n) && wback && (i != lowest_bit_set))
3890 // MemA[address,4] = bits(32) UNKNOWN;
3891 WriteBits32UnknownToMemory (address + offset);
3892 else
3893 {
3894 // MemA[address,4] = R[i];
3895 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3896 if (!success)
3897 return false;
3898
3899 Register data_reg;
3900 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3901 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003902 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003903 return false;
3904 }
3905
3906 // address = address + 4;
3907 offset += addr_byte_size;
3908 }
3909 }
3910
3911 // if registers<15> == ’1’ then
3912 // MemA[address,4] = PCStoreValue();
3913 if (BitIsSet (registers, 15))
3914 {
3915 Register pc_reg;
3916 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3917 context.SetRegisterPlusOffset (pc_reg, 8);
3918 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3919 if (!success)
3920 return false;
3921
Caroline Ticecc96eb52011-02-17 19:20:40 +00003922 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003923 return false;
3924 }
3925
3926 // if wback then R[n] = R[n] - 4*BitCount(registers);
3927 if (wback)
3928 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003929 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003930 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3931 context.SetImmediateSigned (offset);
3932 addr_t data = address + offset;
3933 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3934 return false;
3935 }
3936 }
3937 return true;
3938}
3939
Caroline Ticeaf556562011-02-15 18:42:15 +00003940// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3941// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3942// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003943bool
3944EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3945{
3946#if 0
3947 if ConditionPassed() then
3948 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3949 address = R[n] - 4*BitCount(registers);
3950
3951 for i = 0 to 14
3952 if registers<i> == ’1’ then
3953 if i == n && wback && i != LowestSetBit(registers) then
3954 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3955 else
3956 MemA[address,4] = R[i];
3957 address = address + 4;
3958
3959 if registers<15> == ’1’ then // Only possible for encoding A1
3960 MemA[address,4] = PCStoreValue();
3961
3962 if wback then R[n] = R[n] - 4*BitCount(registers);
3963#endif
3964
3965
3966 bool success = false;
3967 const uint32_t opcode = OpcodeAsUnsigned (&success);
3968 if (!success)
3969 return false;
3970
3971 if (ConditionPassed ())
3972 {
3973 uint32_t n;
3974 uint32_t registers = 0;
3975 bool wback;
3976 const uint32_t addr_byte_size = GetAddressByteSize();
3977
3978 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3979 switch (encoding)
3980 {
3981 case eEncodingT1:
3982 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3983 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3984 {
3985 // See PUSH
3986 }
3987 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3988 n = Bits32 (opcode, 19, 16);
3989 registers = Bits32 (opcode, 15, 0);
3990 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3991 wback = BitIsSet (opcode, 21);
3992 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3993 if ((n == 15) || BitCount (registers) < 2)
3994 return false;
3995 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3996 if (wback && BitIsSet (registers, n))
3997 return false;
3998 break;
3999
4000 case eEncodingA1:
4001 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4002 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4003 {
4004 // See Push
4005 }
4006 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4007 n = Bits32 (opcode, 19, 16);
4008 registers = Bits32 (opcode, 15, 0);
4009 wback = BitIsSet (opcode, 21);
4010 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4011 if ((n == 15) || BitCount (registers) < 1)
4012 return false;
4013 break;
4014
4015 default:
4016 return false;
4017 }
4018
4019 // address = R[n] - 4*BitCount(registers);
4020
4021 int32_t offset = 0;
4022 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4023 if (!success)
4024 return false;
4025
4026 address = address - (addr_byte_size * BitCount (registers));
4027
4028 EmulateInstruction::Context context;
4029 context.type = EmulateInstruction::eContextRegisterStore;
4030 Register base_reg;
4031 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4032
4033 // for i = 0 to 14
4034 for (int i = 0; i < 14; ++i)
4035 {
4036 uint32_t lowest_set_bit = 14;
4037 // if registers<i> == ’1’ then
4038 if (BitIsSet (registers, i))
4039 {
4040 if (i < lowest_set_bit)
4041 lowest_set_bit = i;
4042 // if i == n && wback && i != LowestSetBit(registers) then
4043 if ((i == n) && wback && (i != lowest_set_bit))
4044 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4045 WriteBits32UnknownToMemory (address + offset);
4046 else
4047 {
4048 // MemA[address,4] = R[i];
4049 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4050 if (!success)
4051 return false;
4052
4053 Register data_reg;
4054 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4055 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004056 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004057 return false;
4058 }
4059
4060 // address = address + 4;
4061 offset += addr_byte_size;
4062 }
4063 }
4064
4065 // if registers<15> == ’1’ then // Only possible for encoding A1
4066 // MemA[address,4] = PCStoreValue();
4067 if (BitIsSet (registers, 15))
4068 {
4069 Register pc_reg;
4070 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4071 context.SetRegisterPlusOffset (pc_reg, 8);
4072 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4073 if (!success)
4074 return false;
4075
Caroline Ticecc96eb52011-02-17 19:20:40 +00004076 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004077 return false;
4078 }
4079
4080 // if wback then R[n] = R[n] - 4*BitCount(registers);
4081 if (wback)
4082 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004083 offset = (addr_byte_size * BitCount (registers)) * -1;
4084 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4085 context.SetImmediateSigned (offset);
4086 addr_t data = address + offset;
4087 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4088 return false;
4089 }
4090 }
4091 return true;
4092}
4093
4094// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4095// from a base register. The consecutive memory locations start just above this address, and the address of the last
4096// of those locations can optionally be written back to the base register.
4097bool
4098EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4099{
4100#if 0
4101 if ConditionPassed() then
4102 EncodingSpecificOperations();
4103 address = R[n] + 4;
4104
4105 for i = 0 to 14
4106 if registers<i> == ’1’ then
4107 if i == n && wback && i != LowestSetBit(registers) then
4108 MemA[address,4] = bits(32) UNKNOWN;
4109 else
4110 MemA[address,4] = R[i];
4111 address = address + 4;
4112
4113 if registers<15> == ’1’ then
4114 MemA[address,4] = PCStoreValue();
4115
4116 if wback then R[n] = R[n] + 4*BitCount(registers);
4117#endif
4118
4119 bool success = false;
4120 const uint32_t opcode = OpcodeAsUnsigned (&success);
4121 if (!success)
4122 return false;
4123
4124 if (ConditionPassed())
4125 {
4126 uint32_t n;
4127 uint32_t registers = 0;
4128 bool wback;
4129 const uint32_t addr_byte_size = GetAddressByteSize();
4130
4131 // EncodingSpecificOperations();
4132 switch (encoding)
4133 {
4134 case eEncodingA1:
4135 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4136 n = Bits32 (opcode, 19, 16);
4137 registers = Bits32 (opcode, 15, 0);
4138 wback = BitIsSet (opcode, 21);
4139
4140 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4141 if ((n == 15) && (BitCount (registers) < 1))
4142 return false;
4143 break;
4144 default:
4145 return false;
4146 }
4147 // address = R[n] + 4;
4148
4149 int32_t offset = 0;
4150 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4151 if (!success)
4152 return false;
4153
4154 address = address + addr_byte_size;
4155
4156 EmulateInstruction::Context context;
4157 context.type = EmulateInstruction::eContextRegisterStore;
4158 Register base_reg;
4159 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4160
4161 uint32_t lowest_set_bit = 14;
4162 // for i = 0 to 14
4163 for (int i = 0; i < 14; ++i)
4164 {
4165 // if registers<i> == ’1’ then
4166 if (BitIsSet (registers, i))
4167 {
4168 if (i < lowest_set_bit)
4169 lowest_set_bit = i;
4170 // if i == n && wback && i != LowestSetBit(registers) then
4171 if ((i == n) && wback && (i != lowest_set_bit))
4172 // MemA[address,4] = bits(32) UNKNOWN;
4173 WriteBits32UnknownToMemory (address + offset);
4174 // else
4175 else
4176 {
4177 // MemA[address,4] = R[i];
4178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4179 if (!success)
4180 return false;
4181
4182 Register data_reg;
4183 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4184 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004185 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004186 return false;
4187 }
4188
4189 // address = address + 4;
4190 offset += addr_byte_size;
4191 }
4192 }
4193
4194 // if registers<15> == ’1’ then
4195 // MemA[address,4] = PCStoreValue();
4196 if (BitIsSet (registers, 15))
4197 {
4198 Register pc_reg;
4199 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4200 context.SetRegisterPlusOffset (pc_reg, 8);
4201 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4202 if (!success)
4203 return false;
4204
Caroline Ticecc96eb52011-02-17 19:20:40 +00004205 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004206 return false;
4207 }
4208
4209 // if wback then R[n] = R[n] + 4*BitCount(registers);
4210 if (wback)
4211 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004212 offset = addr_byte_size * BitCount (registers);
4213 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4214 context.SetImmediateSigned (offset);
4215 addr_t data = address + offset;
4216 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4217 return false;
4218 }
4219 }
4220 return true;
4221}
Caroline Tice7fac8572011-02-15 22:53:54 +00004222
4223// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4224// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4225bool
4226EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4227{
4228#if 0
4229 if ConditionPassed() then
4230 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4231 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4232 address = if index then offset_addr else R[n];
4233 if UnalignedSupport() || address<1:0> == ’00’ then
4234 MemU[address,4] = R[t];
4235 else // Can only occur before ARMv7
4236 MemU[address,4] = bits(32) UNKNOWN;
4237 if wback then R[n] = offset_addr;
4238#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004239
Caroline Tice7fac8572011-02-15 22:53:54 +00004240 bool success = false;
4241 const uint32_t opcode = OpcodeAsUnsigned (&success);
4242 if (!success)
4243 return false;
4244
4245 if (ConditionPassed())
4246 {
4247 const uint32_t addr_byte_size = GetAddressByteSize();
4248
4249 uint32_t t;
4250 uint32_t n;
4251 uint32_t imm32;
4252 bool index;
4253 bool add;
4254 bool wback;
4255 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4256 switch (encoding)
4257 {
4258 case eEncodingT1:
4259 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4260 t = Bits32 (opcode, 2, 0);
4261 n = Bits32 (opcode, 5, 3);
4262 imm32 = Bits32 (opcode, 10, 6) << 2;
4263
4264 // index = TRUE; add = TRUE; wback = FALSE;
4265 index = true;
4266 add = false;
4267 wback = false;
4268 break;
4269
4270 case eEncodingT2:
4271 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4272 t = Bits32 (opcode, 10, 8);
4273 n = 13;
4274 imm32 = Bits32 (opcode, 7, 0) << 2;
4275
4276 // index = TRUE; add = TRUE; wback = FALSE;
4277 index = true;
4278 add = true;
4279 wback = false;
4280 break;
4281
4282 case eEncodingT3:
4283 // if Rn == ’1111’ then UNDEFINED;
4284 if (Bits32 (opcode, 19, 16) == 15)
4285 return false;
4286
4287 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4288 t = Bits32 (opcode, 15, 12);
4289 n = Bits32 (opcode, 19, 16);
4290 imm32 = Bits32 (opcode, 11, 0);
4291
4292 // index = TRUE; add = TRUE; wback = FALSE;
4293 index = true;
4294 add = true;
4295 wback = false;
4296
4297 // if t == 15 then UNPREDICTABLE;
4298 if (t == 15)
4299 return false;
4300 break;
4301
4302 case eEncodingT4:
4303 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4304 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4305 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4306 if ((Bits32 (opcode, 19, 16) == 15)
4307 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4308 return false;
4309
4310 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4311 t = Bits32 (opcode, 15, 12);
4312 n = Bits32 (opcode, 19, 16);
4313 imm32 = Bits32 (opcode, 7, 0);
4314
4315 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4316 index = BitIsSet (opcode, 10);
4317 add = BitIsSet (opcode, 9);
4318 wback = BitIsSet (opcode, 8);
4319
4320 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4321 if ((t == 15) || (wback && (n == t)))
4322 return false;
4323 break;
4324
4325 default:
4326 return false;
4327 }
4328
4329 addr_t offset_addr;
4330 addr_t address;
4331
4332 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4333 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4334 if (!success)
4335 return false;
4336
4337 if (add)
4338 offset_addr = base_address + imm32;
4339 else
4340 offset_addr = base_address - imm32;
4341
4342 // address = if index then offset_addr else R[n];
4343 if (index)
4344 address = offset_addr;
4345 else
4346 address = base_address;
4347
4348 EmulateInstruction::Context context;
4349 context.type = eContextRegisterStore;
4350 Register base_reg;
4351 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4352
4353 // if UnalignedSupport() || address<1:0> == ’00’ then
4354 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4355 {
4356 // MemU[address,4] = R[t];
4357 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4358 if (!success)
4359 return false;
4360
4361 Register data_reg;
4362 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4363 int32_t offset = address - base_address;
4364 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004365 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004366 return false;
4367 }
4368 else
4369 {
4370 // MemU[address,4] = bits(32) UNKNOWN;
4371 WriteBits32UnknownToMemory (address);
4372 }
4373
4374 // if wback then R[n] = offset_addr;
4375 if (wback)
4376 {
4377 context.type = eContextRegisterLoad;
4378 context.SetAddress (offset_addr);
4379 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4380 return false;
4381 }
4382 }
4383 return true;
4384}
Caroline Ticeaf556562011-02-15 18:42:15 +00004385
Caroline Tice3fd63e92011-02-16 00:33:43 +00004386// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4387// word from a register to memory. The offset register value can optionally be shifted.
4388bool
4389EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4390{
4391#if 0
4392 if ConditionPassed() then
4393 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4394 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4395 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4396 address = if index then offset_addr else R[n];
4397 if t == 15 then // Only possible for encoding A1
4398 data = PCStoreValue();
4399 else
4400 data = R[t];
4401 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4402 MemU[address,4] = data;
4403 else // Can only occur before ARMv7
4404 MemU[address,4] = bits(32) UNKNOWN;
4405 if wback then R[n] = offset_addr;
4406#endif
4407
4408 bool success = false;
4409 const uint32_t opcode = OpcodeAsUnsigned (&success);
4410 if (!success)
4411 return false;
4412
4413 if (ConditionPassed())
4414 {
4415 const uint32_t addr_byte_size = GetAddressByteSize();
4416
4417 uint32_t t;
4418 uint32_t n;
4419 uint32_t m;
4420 ARM_ShifterType shift_t;
4421 uint32_t shift_n;
4422 bool index;
4423 bool add;
4424 bool wback;
4425
4426 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4427 switch (encoding)
4428 {
4429 case eEncodingT1:
4430 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4431 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4432 t = Bits32 (opcode, 2, 0);
4433 n = Bits32 (opcode, 5, 3);
4434 m = Bits32 (opcode, 8, 6);
4435
4436 // index = TRUE; add = TRUE; wback = FALSE;
4437 index = true;
4438 add = true;
4439 wback = false;
4440
4441 // (shift_t, shift_n) = (SRType_LSL, 0);
4442 shift_t = SRType_LSL;
4443 shift_n = 0;
4444 break;
4445
4446 case eEncodingT2:
4447 // if Rn == ’1111’ then UNDEFINED;
4448 if (Bits32 (opcode, 19, 16) == 15)
4449 return false;
4450
4451 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4452 t = Bits32 (opcode, 15, 12);
4453 n = Bits32 (opcode, 19, 16);
4454 m = Bits32 (opcode, 3, 0);
4455
4456 // index = TRUE; add = TRUE; wback = FALSE;
4457 index = true;
4458 add = true;
4459 wback = false;
4460
4461 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4462 shift_t = SRType_LSL;
4463 shift_n = Bits32 (opcode, 5, 4);
4464
4465 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4466 if ((t == 15) || (BadReg (m)))
4467 return false;
4468 break;
4469
4470 case eEncodingA1:
4471 {
4472 // if P == ’0’ && W == ’1’ then SEE STRT;
4473 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4474 t = Bits32 (opcode, 15, 12);
4475 n = Bits32 (opcode, 19, 16);
4476 m = Bits32 (opcode, 3, 0);
4477
4478 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4479 index = BitIsSet (opcode, 24);
4480 add = BitIsSet (opcode, 23);
4481 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4482
4483 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4484 uint32_t typ = Bits32 (opcode, 6, 5);
4485 uint32_t imm5 = Bits32 (opcode, 11, 7);
4486 shift_n = DecodeImmShift(typ, imm5, shift_t);
4487
4488 // if m == 15 then UNPREDICTABLE;
4489 if (m == 15)
4490 return false;
4491
4492 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4493 if (wback && ((n == 15) || (n == t)))
4494 return false;
4495
4496 break;
4497 }
4498 default:
4499 return false;
4500 }
4501
4502 addr_t offset_addr;
4503 addr_t address;
4504 int32_t offset = 0;
4505
4506 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4507 if (!success)
4508 return false;
4509
4510 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4511 if (!success)
4512 return false;
4513
4514 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004515 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004516
4517 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4518 if (add)
4519 offset_addr = base_address + offset;
4520 else
4521 offset_addr = base_address - offset;
4522
4523 // address = if index then offset_addr else R[n];
4524 if (index)
4525 address = offset_addr;
4526 else
4527 address = base_address;
4528
4529 uint32_t data;
4530 // if t == 15 then // Only possible for encoding A1
4531 if (t == 15)
4532 // data = PCStoreValue();
4533 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4534 else
4535 // data = R[t];
4536 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4537
4538 if (!success)
4539 return false;
4540
4541 EmulateInstruction::Context context;
4542 context.type = eContextRegisterStore;
4543
4544 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4545 if (UnalignedSupport ()
4546 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4547 || CurrentInstrSet() == eModeARM)
4548 {
4549 // MemU[address,4] = data;
4550
4551 Register base_reg;
4552 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4553
4554 Register data_reg;
4555 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4556
4557 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004558 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004559 return false;
4560
4561 }
4562 else
4563 // MemU[address,4] = bits(32) UNKNOWN;
4564 WriteBits32UnknownToMemory (address);
4565
4566 // if wback then R[n] = offset_addr;
4567 if (wback)
4568 {
4569 context.type = eContextRegisterLoad;
4570 context.SetAddress (offset_addr);
4571 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4572 return false;
4573 }
4574
4575 }
4576 return true;
4577}
Caroline Tice73a29de2011-02-16 20:22:22 +00004578
4579bool
4580EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4581{
4582#if 0
4583 if ConditionPassed() then
4584 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4585 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4586 address = if index then offset_addr else R[n];
4587 MemU[address,1] = R[t]<7:0>;
4588 if wback then R[n] = offset_addr;
4589#endif
4590
4591
4592 bool success = false;
4593 const uint32_t opcode = OpcodeAsUnsigned (&success);
4594 if (!success)
4595 return false;
4596
4597 if (ConditionPassed ())
4598 {
4599 uint32_t t;
4600 uint32_t n;
4601 uint32_t imm32;
4602 bool index;
4603 bool add;
4604 bool wback;
4605 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4606 switch (encoding)
4607 {
4608 case eEncodingT1:
4609 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4610 t = Bits32 (opcode, 2, 0);
4611 n = Bits32 (opcode, 5, 3);
4612 imm32 = Bits32 (opcode, 10, 6);
4613
4614 // index = TRUE; add = TRUE; wback = FALSE;
4615 index = true;
4616 add = true;
4617 wback = false;
4618 break;
4619
4620 case eEncodingT2:
4621 // if Rn == ’1111’ then UNDEFINED;
4622 if (Bits32 (opcode, 19, 16) == 15)
4623 return false;
4624
4625 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4626 t = Bits32 (opcode, 15, 12);
4627 n = Bits32 (opcode, 19, 16);
4628 imm32 = Bits32 (opcode, 11, 0);
4629
4630 // index = TRUE; add = TRUE; wback = FALSE;
4631 index = true;
4632 add = true;
4633 wback = false;
4634
4635 // if BadReg(t) then UNPREDICTABLE;
4636 if (BadReg (t))
4637 return false;
4638 break;
4639
4640 case eEncodingT3:
4641 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4642 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4643 if (Bits32 (opcode, 19, 16) == 15)
4644 return false;
4645
4646 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4647 t = Bits32 (opcode, 15, 12);
4648 n = Bits32 (opcode, 19, 16);
4649 imm32 = Bits32 (opcode, 7, 0);
4650
4651 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4652 index = BitIsSet (opcode, 10);
4653 add = BitIsSet (opcode, 9);
4654 wback = BitIsSet (opcode, 8);
4655
4656 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4657 if ((BadReg (t)) || (wback && (n == t)))
4658 return false;
4659 break;
4660
4661 default:
4662 return false;
4663 }
4664
4665 addr_t offset_addr;
4666 addr_t address;
4667 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4668 if (!success)
4669 return false;
4670
4671 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4672 if (add)
4673 offset_addr = base_address + imm32;
4674 else
4675 offset_addr = base_address - imm32;
4676
4677 // address = if index then offset_addr else R[n];
4678 if (index)
4679 address = offset_addr;
4680 else
4681 address = base_address;
4682
Caroline Ticecc96eb52011-02-17 19:20:40 +00004683 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004684 Register base_reg;
4685 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4686
4687 Register data_reg;
4688 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4689
4690 EmulateInstruction::Context context;
4691 context.type = eContextRegisterStore;
4692 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4693
4694 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4695 if (!success)
4696 return false;
4697
4698 data = Bits32 (data, 7, 0);
4699
Caroline Ticecc96eb52011-02-17 19:20:40 +00004700 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004701 return false;
4702
4703 // if wback then R[n] = offset_addr;
4704 if (wback)
4705 {
4706 context.type = eContextRegisterLoad;
4707 context.SetAddress (offset_addr);
4708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4709 return false;
4710 }
4711
4712 }
4713
4714 return true;
4715}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004716
Johnny Chen157b9592011-02-18 21:13:05 +00004717// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4718// and writes the result to the destination register. It can optionally update the condition flags
4719// based on the result.
4720bool
4721EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4722{
4723#if 0
4724 // ARM pseudo code...
4725 if ConditionPassed() then
4726 EncodingSpecificOperations();
4727 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4728 if d == 15 then // Can only occur for ARM encoding
4729 ALUWritePC(result); // setflags is always FALSE here
4730 else
4731 R[d] = result;
4732 if setflags then
4733 APSR.N = result<31>;
4734 APSR.Z = IsZeroBit(result);
4735 APSR.C = carry;
4736 APSR.V = overflow;
4737#endif
4738
4739 bool success = false;
4740 const uint32_t opcode = OpcodeAsUnsigned (&success);
4741 if (!success)
4742 return false;
4743
4744 if (ConditionPassed())
4745 {
4746 uint32_t Rd, Rn;
4747 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4748 bool setflags;
4749 switch (encoding)
4750 {
4751 case eEncodingT1:
4752 Rd = Bits32(opcode, 11, 8);
4753 Rn = Bits32(opcode, 19, 16);
4754 setflags = BitIsSet(opcode, 20);
4755 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4756 if (BadReg(Rd) || BadReg(Rn))
4757 return false;
4758 break;
4759 case eEncodingA1:
4760 Rd = Bits32(opcode, 15, 12);
4761 Rn = Bits32(opcode, 19, 16);
4762 setflags = BitIsSet(opcode, 20);
4763 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4764 // TODO: Emulate SUBS PC, LR and related instructions.
4765 if (Rd == 15 && setflags)
4766 return false;
4767 break;
4768 default:
4769 return false;
4770 }
4771
4772 // Read the first operand.
4773 int32_t val1 = ReadCoreReg(Rn, &success);
4774 if (!success)
4775 return false;
4776
4777 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4778
4779 EmulateInstruction::Context context;
4780 context.type = EmulateInstruction::eContextImmediate;
4781 context.SetNoArgs ();
4782
4783 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4784 return false;
4785 }
4786 return true;
4787}
4788
4789// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4790// register value, and writes the result to the destination register. It can optionally update the
4791// condition flags based on the result.
4792bool
4793EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4794{
4795#if 0
4796 // ARM pseudo code...
4797 if ConditionPassed() then
4798 EncodingSpecificOperations();
4799 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4800 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4801 if d == 15 then // Can only occur for ARM encoding
4802 ALUWritePC(result); // setflags is always FALSE here
4803 else
4804 R[d] = result;
4805 if setflags then
4806 APSR.N = result<31>;
4807 APSR.Z = IsZeroBit(result);
4808 APSR.C = carry;
4809 APSR.V = overflow;
4810#endif
4811
4812 bool success = false;
4813 const uint32_t opcode = OpcodeAsUnsigned (&success);
4814 if (!success)
4815 return false;
4816
4817 if (ConditionPassed())
4818 {
4819 uint32_t Rd, Rn, Rm;
4820 ARM_ShifterType shift_t;
4821 uint32_t shift_n; // the shift applied to the value read from Rm
4822 bool setflags;
4823 switch (encoding)
4824 {
4825 case eEncodingT1:
4826 Rd = Rn = Bits32(opcode, 2, 0);
4827 Rm = Bits32(opcode, 5, 3);
4828 setflags = !InITBlock();
4829 shift_t = SRType_LSL;
4830 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004831 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004832 case eEncodingT2:
4833 Rd = Bits32(opcode, 11, 8);
4834 Rn = Bits32(opcode, 19, 16);
4835 Rm = Bits32(opcode, 3, 0);
4836 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004837 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004838 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4839 return false;
4840 break;
4841 case eEncodingA1:
4842 Rd = Bits32(opcode, 15, 12);
4843 Rn = Bits32(opcode, 19, 16);
4844 Rm = Bits32(opcode, 3, 0);
4845 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004846 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004847 // TODO: Emulate SUBS PC, LR and related instructions.
4848 if (Rd == 15 && setflags)
4849 return false;
4850 break;
4851 default:
4852 return false;
4853 }
4854
4855 // Read the first operand.
4856 int32_t val1 = ReadCoreReg(Rn, &success);
4857 if (!success)
4858 return false;
4859
4860 // Read the second operand.
4861 int32_t val2 = ReadCoreReg(Rm, &success);
4862 if (!success)
4863 return false;
4864
4865 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4866 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4867
4868 EmulateInstruction::Context context;
4869 context.type = EmulateInstruction::eContextImmediate;
4870 context.SetNoArgs ();
4871
4872 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4873 return false;
4874 }
4875 return true;
4876}
4877
Johnny Chena695f952011-02-23 21:24:25 +00004878// This instruction adds an immediate value to the PC value to form a PC-relative address,
4879// and writes the result to the destination register.
4880bool
4881EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4882{
4883#if 0
4884 // ARM pseudo code...
4885 if ConditionPassed() then
4886 EncodingSpecificOperations();
4887 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
4888 if d == 15 then // Can only occur for ARM encodings
4889 ALUWritePC(result);
4890 else
4891 R[d] = result;
4892#endif
4893
4894 bool success = false;
4895 const uint32_t opcode = OpcodeAsUnsigned (&success);
4896 if (!success)
4897 return false;
4898
4899 if (ConditionPassed())
4900 {
4901 uint32_t Rd;
4902 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
4903 bool add;
4904 switch (encoding)
4905 {
4906 case eEncodingT1:
4907 Rd = Bits32(opcode, 10, 8);
4908 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
4909 break;
4910 case eEncodingT2:
4911 case eEncodingT3:
4912 Rd = Bits32(opcode, 11, 8);
4913 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
4914 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
4915 if (BadReg(Rd))
4916 return false;
4917 break;
4918 case eEncodingA1:
4919 case eEncodingA2:
4920 Rd = Bits32(opcode, 15, 12);
4921 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4922 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
4923 break;
4924 default:
4925 return false;
4926 }
4927
4928 // Read the PC value.
4929 uint32_t pc = ReadCoreReg(PC_REG, &success);
4930 if (!success)
4931 return false;
4932
4933 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
4934
4935 EmulateInstruction::Context context;
4936 context.type = EmulateInstruction::eContextImmediate;
4937 context.SetNoArgs ();
4938
4939 if (!WriteCoreReg(context, result, Rd))
4940 return false;
4941 }
4942 return true;
4943}
4944
Johnny Chene97c0d52011-02-18 19:32:20 +00004945// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4946// to the destination register. It can optionally update the condition flags based on the result.
4947bool
4948EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4949{
4950#if 0
4951 // ARM pseudo code...
4952 if ConditionPassed() then
4953 EncodingSpecificOperations();
4954 result = R[n] AND imm32;
4955 if d == 15 then // Can only occur for ARM encoding
4956 ALUWritePC(result); // setflags is always FALSE here
4957 else
4958 R[d] = result;
4959 if setflags then
4960 APSR.N = result<31>;
4961 APSR.Z = IsZeroBit(result);
4962 APSR.C = carry;
4963 // APSR.V unchanged
4964#endif
4965
4966 bool success = false;
4967 const uint32_t opcode = OpcodeAsUnsigned (&success);
4968 if (!success)
4969 return false;
4970
4971 if (ConditionPassed())
4972 {
4973 uint32_t Rd, Rn;
4974 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4975 bool setflags;
4976 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4977 switch (encoding)
4978 {
4979 case eEncodingT1:
4980 Rd = Bits32(opcode, 11, 8);
4981 Rn = Bits32(opcode, 19, 16);
4982 setflags = BitIsSet(opcode, 20);
4983 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004984 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004985 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004986 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004987 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4988 return false;
4989 break;
4990 case eEncodingA1:
4991 Rd = Bits32(opcode, 15, 12);
4992 Rn = Bits32(opcode, 19, 16);
4993 setflags = BitIsSet(opcode, 20);
4994 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4995 // TODO: Emulate SUBS PC, LR and related instructions.
4996 if (Rd == 15 && setflags)
4997 return false;
4998 break;
4999 default:
5000 return false;
5001 }
5002
Johnny Chene97c0d52011-02-18 19:32:20 +00005003 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005004 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005005 if (!success)
5006 return false;
5007
5008 uint32_t result = val1 & imm32;
5009
5010 EmulateInstruction::Context context;
5011 context.type = EmulateInstruction::eContextImmediate;
5012 context.SetNoArgs ();
5013
5014 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5015 return false;
5016 }
5017 return true;
5018}
5019
5020// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5021// and writes the result to the destination register. It can optionally update the condition flags
5022// based on the result.
5023bool
5024EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5025{
5026#if 0
5027 // ARM pseudo code...
5028 if ConditionPassed() then
5029 EncodingSpecificOperations();
5030 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5031 result = R[n] AND shifted;
5032 if d == 15 then // Can only occur for ARM encoding
5033 ALUWritePC(result); // setflags is always FALSE here
5034 else
5035 R[d] = result;
5036 if setflags then
5037 APSR.N = result<31>;
5038 APSR.Z = IsZeroBit(result);
5039 APSR.C = carry;
5040 // APSR.V unchanged
5041#endif
5042
5043 bool success = false;
5044 const uint32_t opcode = OpcodeAsUnsigned (&success);
5045 if (!success)
5046 return false;
5047
5048 if (ConditionPassed())
5049 {
5050 uint32_t Rd, Rn, Rm;
5051 ARM_ShifterType shift_t;
5052 uint32_t shift_n; // the shift applied to the value read from Rm
5053 bool setflags;
5054 uint32_t carry;
5055 switch (encoding)
5056 {
5057 case eEncodingT1:
5058 Rd = Rn = Bits32(opcode, 2, 0);
5059 Rm = Bits32(opcode, 5, 3);
5060 setflags = !InITBlock();
5061 shift_t = SRType_LSL;
5062 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005063 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005064 case eEncodingT2:
5065 Rd = Bits32(opcode, 11, 8);
5066 Rn = Bits32(opcode, 19, 16);
5067 Rm = Bits32(opcode, 3, 0);
5068 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005069 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005070 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005071 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005072 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005073 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5074 return false;
5075 break;
5076 case eEncodingA1:
5077 Rd = Bits32(opcode, 15, 12);
5078 Rn = Bits32(opcode, 19, 16);
5079 Rm = Bits32(opcode, 3, 0);
5080 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005081 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005082 // TODO: Emulate SUBS PC, LR and related instructions.
5083 if (Rd == 15 && setflags)
5084 return false;
5085 break;
5086 default:
5087 return false;
5088 }
5089
Johnny Chene97c0d52011-02-18 19:32:20 +00005090 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005091 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005092 if (!success)
5093 return false;
5094
5095 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005096 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005097 if (!success)
5098 return false;
5099
5100 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5101 uint32_t result = val1 & shifted;
5102
5103 EmulateInstruction::Context context;
5104 context.type = EmulateInstruction::eContextImmediate;
5105 context.SetNoArgs ();
5106
5107 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5108 return false;
5109 }
5110 return true;
5111}
5112
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005113// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5114// immediate value, and writes the result to the destination register. It can optionally update the
5115// condition flags based on the result.
5116bool
5117EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5118{
5119#if 0
5120 // ARM pseudo code...
5121 if ConditionPassed() then
5122 EncodingSpecificOperations();
5123 result = R[n] AND NOT(imm32);
5124 if d == 15 then // Can only occur for ARM encoding
5125 ALUWritePC(result); // setflags is always FALSE here
5126 else
5127 R[d] = result;
5128 if setflags then
5129 APSR.N = result<31>;
5130 APSR.Z = IsZeroBit(result);
5131 APSR.C = carry;
5132 // APSR.V unchanged
5133#endif
5134
5135 bool success = false;
5136 const uint32_t opcode = OpcodeAsUnsigned (&success);
5137 if (!success)
5138 return false;
5139
5140 if (ConditionPassed())
5141 {
5142 uint32_t Rd, Rn;
5143 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5144 bool setflags;
5145 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5146 switch (encoding)
5147 {
5148 case eEncodingT1:
5149 Rd = Bits32(opcode, 11, 8);
5150 Rn = Bits32(opcode, 19, 16);
5151 setflags = BitIsSet(opcode, 20);
5152 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5153 if (BadReg(Rd) || BadReg(Rn))
5154 return false;
5155 break;
5156 case eEncodingA1:
5157 Rd = Bits32(opcode, 15, 12);
5158 Rn = Bits32(opcode, 19, 16);
5159 setflags = BitIsSet(opcode, 20);
5160 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5161 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5162 // TODO: Emulate SUBS PC, LR and related instructions.
5163 if (Rd == 15 && setflags)
5164 return false;
5165 break;
5166 default:
5167 return false;
5168 }
5169
5170 // Read the first operand.
5171 uint32_t val1 = ReadCoreReg(Rn, &success);
5172 if (!success)
5173 return false;
5174
5175 uint32_t result = val1 & ~imm32;
5176
5177 EmulateInstruction::Context context;
5178 context.type = EmulateInstruction::eContextImmediate;
5179 context.SetNoArgs ();
5180
5181 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5182 return false;
5183 }
5184 return true;
5185}
5186
5187// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5188// optionally-shifted register value, and writes the result to the destination register.
5189// It can optionally update the condition flags based on the result.
5190bool
5191EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5192{
5193#if 0
5194 // ARM pseudo code...
5195 if ConditionPassed() then
5196 EncodingSpecificOperations();
5197 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5198 result = R[n] AND NOT(shifted);
5199 if d == 15 then // Can only occur for ARM encoding
5200 ALUWritePC(result); // setflags is always FALSE here
5201 else
5202 R[d] = result;
5203 if setflags then
5204 APSR.N = result<31>;
5205 APSR.Z = IsZeroBit(result);
5206 APSR.C = carry;
5207 // APSR.V unchanged
5208#endif
5209
5210 bool success = false;
5211 const uint32_t opcode = OpcodeAsUnsigned (&success);
5212 if (!success)
5213 return false;
5214
5215 if (ConditionPassed())
5216 {
5217 uint32_t Rd, Rn, Rm;
5218 ARM_ShifterType shift_t;
5219 uint32_t shift_n; // the shift applied to the value read from Rm
5220 bool setflags;
5221 uint32_t carry;
5222 switch (encoding)
5223 {
5224 case eEncodingT1:
5225 Rd = Rn = Bits32(opcode, 2, 0);
5226 Rm = Bits32(opcode, 5, 3);
5227 setflags = !InITBlock();
5228 shift_t = SRType_LSL;
5229 shift_n = 0;
5230 break;
5231 case eEncodingT2:
5232 Rd = Bits32(opcode, 11, 8);
5233 Rn = Bits32(opcode, 19, 16);
5234 Rm = Bits32(opcode, 3, 0);
5235 setflags = BitIsSet(opcode, 20);
5236 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5237 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5238 return false;
5239 break;
5240 case eEncodingA1:
5241 Rd = Bits32(opcode, 15, 12);
5242 Rn = Bits32(opcode, 19, 16);
5243 Rm = Bits32(opcode, 3, 0);
5244 setflags = BitIsSet(opcode, 20);
5245 shift_n = DecodeImmShiftARM(opcode, shift_t);
5246 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5247 // TODO: Emulate SUBS PC, LR and related instructions.
5248 if (Rd == 15 && setflags)
5249 return false;
5250 break;
5251 default:
5252 return false;
5253 }
5254
5255 // Read the first operand.
5256 uint32_t val1 = ReadCoreReg(Rn, &success);
5257 if (!success)
5258 return false;
5259
5260 // Read the second operand.
5261 uint32_t val2 = ReadCoreReg(Rm, &success);
5262 if (!success)
5263 return false;
5264
5265 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5266 uint32_t result = val1 & ~shifted;
5267
5268 EmulateInstruction::Context context;
5269 context.type = EmulateInstruction::eContextImmediate;
5270 context.SetNoArgs ();
5271
5272 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5273 return false;
5274 }
5275 return true;
5276}
5277
Caroline Tice4d729c52011-02-18 00:55:53 +00005278// 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 +00005279// 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 +00005280bool
5281EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5282{
5283#if 0
5284 if ConditionPassed() then
5285 EncodingSpecificOperations();
5286 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5287 address = if index then offset_addr else R[n];
5288 data = MemU[address,4];
5289 if wback then R[n] = offset_addr;
5290 if t == 15 then
5291 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5292 elsif UnalignedSupport() || address<1:0> = ’00’ then
5293 R[t] = data;
5294 else // Can only apply before ARMv7
5295 R[t] = ROR(data, 8*UInt(address<1:0>));
5296#endif
5297
5298 bool success = false;
5299 const uint32_t opcode = OpcodeAsUnsigned (&success);
5300 if (!success)
5301 return false;
5302
5303 if (ConditionPassed ())
5304 {
5305 const uint32_t addr_byte_size = GetAddressByteSize();
5306
5307 uint32_t t;
5308 uint32_t n;
5309 uint32_t imm32;
5310 bool index;
5311 bool add;
5312 bool wback;
5313
5314 switch (encoding)
5315 {
5316 case eEncodingA1:
5317 // if Rn == ’1111’ then SEE LDR (literal);
5318 // if P == ’0’ && W == ’1’ then SEE LDRT;
5319 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5320 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5321 t = Bits32 (opcode, 15, 12);
5322 n = Bits32 (opcode, 19, 16);
5323 imm32 = Bits32 (opcode, 11, 0);
5324
5325 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5326 index = BitIsSet (opcode, 24);
5327 add = BitIsSet (opcode, 23);
5328 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5329
5330 // if wback && n == t then UNPREDICTABLE;
5331 if (wback && (n == t))
5332 return false;
5333
5334 break;
5335
5336 default:
5337 return false;
5338 }
5339
5340 addr_t address;
5341 addr_t offset_addr;
5342 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5343 if (!success)
5344 return false;
5345
5346 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5347 if (add)
5348 offset_addr = base_address + imm32;
5349 else
5350 offset_addr = base_address - imm32;
5351
5352 // address = if index then offset_addr else R[n];
5353 if (index)
5354 address = offset_addr;
5355 else
5356 address = base_address;
5357
5358 // data = MemU[address,4];
5359
5360 Register base_reg;
5361 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5362
5363 EmulateInstruction::Context context;
5364 context.type = eContextRegisterLoad;
5365 context.SetRegisterPlusOffset (base_reg, address - base_address);
5366
5367 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5368 if (!success)
5369 return false;
5370
5371 // if wback then R[n] = offset_addr;
5372 if (wback)
5373 {
5374 context.type = eContextAdjustBaseRegister;
5375 context.SetAddress (offset_addr);
5376 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5377 return false;
5378 }
5379
5380 // if t == 15 then
5381 if (t == 15)
5382 {
5383 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5384 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5385 {
5386 // LoadWritePC (data);
5387 context.type = eContextRegisterLoad;
5388 context.SetRegisterPlusOffset (base_reg, address - base_address);
5389 LoadWritePC (context, data);
5390 }
5391 else
5392 return false;
5393 }
5394 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5395 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5396 {
5397 // R[t] = data;
5398 context.type = eContextRegisterLoad;
5399 context.SetRegisterPlusOffset (base_reg, address - base_address);
5400 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5401 return false;
5402 }
5403 // else // Can only apply before ARMv7
5404 else
5405 {
5406 // R[t] = ROR(data, 8*UInt(address<1:0>));
5407 data = ROR (data, Bits32 (address, 1, 0));
5408 context.type = eContextRegisterLoad;
5409 context.SetImmediate (data);
5410 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5411 return false;
5412 }
5413
5414 }
5415 return true;
5416}
5417
Caroline Ticefe479112011-02-18 18:52:37 +00005418// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5419// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5420bool
5421EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5422{
5423#if 0
5424 if ConditionPassed() then
5425 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5426 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5427 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5428 address = if index then offset_addr else R[n];
5429 data = MemU[address,4];
5430 if wback then R[n] = offset_addr;
5431 if t == 15 then
5432 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5433 elsif UnalignedSupport() || address<1:0> = ’00’ then
5434 R[t] = data;
5435 else // Can only apply before ARMv7
5436 if CurrentInstrSet() == InstrSet_ARM then
5437 R[t] = ROR(data, 8*UInt(address<1:0>));
5438 else
5439 R[t] = bits(32) UNKNOWN;
5440#endif
5441
5442 bool success = false;
5443 const uint32_t opcode = OpcodeAsUnsigned (&success);
5444 if (!success)
5445 return false;
5446
5447 if (ConditionPassed ())
5448 {
5449 const uint32_t addr_byte_size = GetAddressByteSize();
5450
5451 uint32_t t;
5452 uint32_t n;
5453 uint32_t m;
5454 bool index;
5455 bool add;
5456 bool wback;
5457 ARM_ShifterType shift_t;
5458 uint32_t shift_n;
5459
5460 switch (encoding)
5461 {
5462 case eEncodingT1:
5463 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5464 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5465 t = Bits32 (opcode, 2, 0);
5466 n = Bits32 (opcode, 5, 3);
5467 m = Bits32 (opcode, 8, 6);
5468
5469 // index = TRUE; add = TRUE; wback = FALSE;
5470 index = true;
5471 add = true;
5472 wback = false;
5473
5474 // (shift_t, shift_n) = (SRType_LSL, 0);
5475 shift_t = SRType_LSL;
5476 shift_n = 0;
5477
5478 break;
5479
5480 case eEncodingT2:
5481 // if Rn == ’1111’ then SEE LDR (literal);
5482 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5483 t = Bits32 (opcode, 15, 12);
5484 n = Bits32 (opcode, 19, 16);
5485 m = Bits32 (opcode, 3, 0);
5486
5487 // index = TRUE; add = TRUE; wback = FALSE;
5488 index = true;
5489 add = true;
5490 wback = false;
5491
5492 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5493 shift_t = SRType_LSL;
5494 shift_n = Bits32 (opcode, 5, 4);
5495
5496 // if BadReg(m) then UNPREDICTABLE;
5497 if (BadReg (m))
5498 return false;
5499
5500 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5501 if ((t == 15) && InITBlock() && !LastInITBlock())
5502 return false;
5503
5504 break;
5505
5506 case eEncodingA1:
5507 {
5508 // if P == ’0’ && W == ’1’ then SEE LDRT;
5509 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5510 t = Bits32 (opcode, 15, 12);
5511 n = Bits32 (opcode, 19, 16);
5512 m = Bits32 (opcode, 3, 0);
5513
5514 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5515 index = BitIsSet (opcode, 24);
5516 add = BitIsSet (opcode, 23);
5517 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5518
5519 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5520 uint32_t type = Bits32 (opcode, 6, 5);
5521 uint32_t imm5 = Bits32 (opcode, 11, 7);
5522 shift_n = DecodeImmShift (type, imm5, shift_t);
5523
5524 // if m == 15 then UNPREDICTABLE;
5525 if (m == 15)
5526 return false;
5527
5528 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5529 if (wback && ((n == 15) || (n == t)))
5530 return false;
5531 }
5532 break;
5533
5534
5535 default:
5536 return false;
5537 }
5538
5539 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5540 if (!success)
5541 return false;
5542
5543 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5544 if (!success)
5545 return false;
5546
5547 addr_t offset_addr;
5548 addr_t address;
5549
5550 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chen90e607b2011-02-23 00:07:09 +00005551 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005552
5553 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5554 if (add)
5555 offset_addr = Rn + offset;
5556 else
5557 offset_addr = Rn - offset;
5558
5559 // address = if index then offset_addr else R[n];
5560 if (index)
5561 address = offset_addr;
5562 else
5563 address = Rn;
5564
5565 // data = MemU[address,4];
5566 Register base_reg;
5567 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5568
5569 EmulateInstruction::Context context;
5570 context.type = eContextRegisterLoad;
5571 context.SetRegisterPlusOffset (base_reg, address - Rn);
5572
5573 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5574 if (!success)
5575 return false;
5576
5577 // if wback then R[n] = offset_addr;
5578 if (wback)
5579 {
5580 context.type = eContextAdjustBaseRegister;
5581 context.SetAddress (offset_addr);
5582 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5583 return false;
5584 }
5585
5586 // if t == 15 then
5587 if (t == 15)
5588 {
5589 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5590 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5591 {
5592 context.type = eContextRegisterLoad;
5593 context.SetRegisterPlusOffset (base_reg, address - Rn);
5594 LoadWritePC (context, data);
5595 }
5596 else
5597 return false;
5598 }
5599 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5600 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5601 {
5602 // R[t] = data;
5603 context.type = eContextRegisterLoad;
5604 context.SetRegisterPlusOffset (base_reg, address - Rn);
5605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5606 return false;
5607 }
5608 else // Can only apply before ARMv7
5609 {
5610 // if CurrentInstrSet() == InstrSet_ARM then
5611 if (CurrentInstrSet () == eModeARM)
5612 {
5613 // R[t] = ROR(data, 8*UInt(address<1:0>));
5614 data = ROR (data, Bits32 (address, 1, 0));
5615 context.type = eContextRegisterLoad;
5616 context.SetImmediate (data);
5617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5618 return false;
5619 }
5620 else
5621 {
5622 // R[t] = bits(32) UNKNOWN;
5623 WriteBits32Unknown (t);
5624 }
5625 }
5626 }
5627 return true;
5628}
Caroline Tice21b604b2011-02-18 21:06:04 +00005629
5630// LDRB (immediate, Thumb)
5631bool
5632EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5633{
5634#if 0
5635 if ConditionPassed() then
5636 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5637 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5638 address = if index then offset_addr else R[n];
5639 R[t] = ZeroExtend(MemU[address,1], 32);
5640 if wback then R[n] = offset_addr;
5641#endif
5642
5643 bool success = false;
5644 const uint32_t opcode = OpcodeAsUnsigned (&success);
5645 if (!success)
5646 return false;
5647
5648 if (ConditionPassed ())
5649 {
5650 uint32_t t;
5651 uint32_t n;
5652 uint32_t imm32;
5653 bool index;
5654 bool add;
5655 bool wback;
5656
5657 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5658 switch (encoding)
5659 {
5660 case eEncodingT1:
5661 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5662 t = Bits32 (opcode, 2, 0);
5663 n = Bits32 (opcode, 5, 3);
5664 imm32 = Bits32 (opcode, 10, 6);
5665
5666 // index = TRUE; add = TRUE; wback = FALSE;
5667 index = true;
5668 add = true;
5669 wback= false;
5670
5671 break;
5672
5673 case eEncodingT2:
5674 // if Rt == ’1111’ then SEE PLD;
5675 // if Rn == ’1111’ then SEE LDRB (literal);
5676 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5677 t = Bits32 (opcode, 15, 12);
5678 n = Bits32 (opcode, 19, 16);
5679 imm32 = Bits32 (opcode, 11, 0);
5680
5681 // index = TRUE; add = TRUE; wback = FALSE;
5682 index = true;
5683 add = true;
5684 wback = false;
5685
5686 // if t == 13 then UNPREDICTABLE;
5687 if (t == 13)
5688 return false;
5689
5690 break;
5691
5692 case eEncodingT3:
5693 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5694 // if Rn == ’1111’ then SEE LDRB (literal);
5695 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5696 // if P == ’0’ && W == ’0’ then UNDEFINED;
5697 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5698 return false;
5699
5700 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5701 t = Bits32 (opcode, 15, 12);
5702 n = Bits32 (opcode, 19, 16);
5703 imm32 = Bits32 (opcode, 7, 0);
5704
5705 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5706 index = BitIsSet (opcode, 10);
5707 add = BitIsSet (opcode, 9);
5708 wback = BitIsSet (opcode, 8);
5709
5710 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5711 if (BadReg (t) || (wback && (n == t)))
5712 return false;
5713
5714 break;
5715
5716 default:
5717 return false;
5718 }
5719
5720 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5721 if (!success)
5722 return false;
5723
5724 addr_t address;
5725 addr_t offset_addr;
5726
5727 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5728 if (add)
5729 offset_addr = Rn + imm32;
5730 else
5731 offset_addr = Rn - imm32;
5732
5733 // address = if index then offset_addr else R[n];
5734 if (index)
5735 address = offset_addr;
5736 else
5737 address = Rn;
5738
5739 // R[t] = ZeroExtend(MemU[address,1], 32);
5740 Register base_reg;
5741 Register data_reg;
5742 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5743 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5744
5745 EmulateInstruction::Context context;
5746 context.type = eContextRegisterLoad;
5747 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5748
5749 uint64_t data = MemURead (context, address, 1, 0, &success);
5750 if (!success)
5751 return false;
5752
5753 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5754 return false;
5755
5756 // if wback then R[n] = offset_addr;
5757 if (wback)
5758 {
5759 context.type = eContextAdjustBaseRegister;
5760 context.SetAddress (offset_addr);
5761 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5762 return false;
5763 }
5764 }
5765 return true;
5766}
Caroline Ticef55261f2011-02-18 22:24:22 +00005767
5768// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5769// zero-extends it to form a 32-bit word and writes it to a register.
5770bool
5771EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5772{
5773#if 0
5774 if ConditionPassed() then
5775 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5776 base = Align(PC,4);
5777 address = if add then (base + imm32) else (base - imm32);
5778 R[t] = ZeroExtend(MemU[address,1], 32);
5779#endif
5780
5781 bool success = false;
5782 const uint32_t opcode = OpcodeAsUnsigned (&success);
5783 if (!success)
5784 return false;
5785
5786 if (ConditionPassed ())
5787 {
5788 uint32_t t;
5789 uint32_t imm32;
5790 bool add;
5791 switch (encoding)
5792 {
5793 case eEncodingT1:
5794 // if Rt == ’1111’ then SEE PLD;
5795 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5796 t = Bits32 (opcode, 15, 12);
5797 imm32 = Bits32 (opcode, 11, 0);
5798 add = BitIsSet (opcode, 23);
5799
5800 // if t == 13 then UNPREDICTABLE;
5801 if (t == 13)
5802 return false;
5803
5804 break;
5805
5806 case eEncodingA1:
5807 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5808 t = Bits32 (opcode, 15, 12);
5809 imm32 = Bits32 (opcode, 11, 0);
5810 add = BitIsSet (opcode, 23);
5811
5812 // if t == 15 then UNPREDICTABLE;
5813 if (t == 15)
5814 return false;
5815 break;
5816
5817 default:
5818 return false;
5819 }
5820
5821 // base = Align(PC,4);
5822 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5823 if (!success)
5824 return false;
5825
5826 uint32_t base = AlignPC (pc_val);
5827
5828 addr_t address;
5829 // address = if add then (base + imm32) else (base - imm32);
5830 if (add)
5831 address = base + imm32;
5832 else
5833 address = base - imm32;
5834
5835 // R[t] = ZeroExtend(MemU[address,1], 32);
5836 EmulateInstruction::Context context;
5837 context.type = eContextRelativeBranchImmediate;
5838 context.SetImmediate (address - base);
5839
5840 uint64_t data = MemURead (context, address, 1, 0, &success);
5841 if (!success)
5842 return false;
5843
5844 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5845 return false;
5846 }
5847 return true;
5848}
Caroline Tice30fec122011-02-18 23:52:21 +00005849
5850// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5851// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5852// optionally be shifted.
5853bool
5854EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5855{
5856#if 0
5857 if ConditionPassed() then
5858 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5859 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5860 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5861 address = if index then offset_addr else R[n];
5862 R[t] = ZeroExtend(MemU[address,1],32);
5863 if wback then R[n] = offset_addr;
5864#endif
5865
5866 bool success = false;
5867 const uint32_t opcode = OpcodeAsUnsigned (&success);
5868 if (!success)
5869 return false;
5870
5871 if (ConditionPassed ())
5872 {
5873 uint32_t t;
5874 uint32_t n;
5875 uint32_t m;
5876 bool index;
5877 bool add;
5878 bool wback;
5879 ARM_ShifterType shift_t;
5880 uint32_t shift_n;
5881
5882 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5883 switch (encoding)
5884 {
5885 case eEncodingT1:
5886 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5887 t = Bits32 (opcode, 2, 0);
5888 n = Bits32 (opcode, 5, 3);
5889 m = Bits32 (opcode, 8, 6);
5890
5891 // index = TRUE; add = TRUE; wback = FALSE;
5892 index = true;
5893 add = true;
5894 wback = false;
5895
5896 // (shift_t, shift_n) = (SRType_LSL, 0);
5897 shift_t = SRType_LSL;
5898 shift_n = 0;
5899 break;
5900
5901 case eEncodingT2:
5902 // if Rt == ’1111’ then SEE PLD;
5903 // if Rn == ’1111’ then SEE LDRB (literal);
5904 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5905 t = Bits32 (opcode, 15, 12);
5906 n = Bits32 (opcode, 19, 16);
5907 m = Bits32 (opcode, 3, 0);
5908
5909 // index = TRUE; add = TRUE; wback = FALSE;
5910 index = true;
5911 add = true;
5912 wback = false;
5913
5914 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5915 shift_t = SRType_LSL;
5916 shift_n = Bits32 (opcode, 5, 4);
5917
5918 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5919 if ((t == 13) || BadReg (m))
5920 return false;
5921 break;
5922
5923 case eEncodingA1:
5924 {
5925 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5926 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5927 t = Bits32 (opcode, 15, 12);
5928 n = Bits32 (opcode, 19, 16);
5929 m = Bits32 (opcode, 3, 0);
5930
5931 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5932 index = BitIsSet (opcode, 24);
5933 add = BitIsSet (opcode, 23);
5934 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5935
5936 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5937 uint32_t type = Bits32 (opcode, 6, 5);
5938 uint32_t imm5 = Bits32 (opcode, 11, 7);
5939 shift_n = DecodeImmShift (type, imm5, shift_t);
5940
5941 // if t == 15 || m == 15 then UNPREDICTABLE;
5942 if ((t == 15) || (m == 15))
5943 return false;
5944
5945 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5946 if (wback && ((n == 15) || (n == t)))
5947 return false;
5948 }
5949 break;
5950
5951 default:
5952 return false;
5953 }
5954
5955 addr_t offset_addr;
5956 addr_t address;
5957
5958 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5959 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5960 if (!success)
5961 return false;
5962
5963 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5964
5965 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5966 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5967 if (!success)
5968 return false;
5969
5970 if (add)
5971 offset_addr = Rn + offset;
5972 else
5973 offset_addr = Rn - offset;
5974
5975 // address = if index then offset_addr else R[n];
5976 if (index)
5977 address = offset_addr;
5978 else
5979 address = Rn;
5980
5981 // R[t] = ZeroExtend(MemU[address,1],32);
5982 Register base_reg;
5983 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5984
5985 EmulateInstruction::Context context;
5986 context.type = eContextRegisterLoad;
5987 context.SetRegisterPlusOffset (base_reg, address - Rn);
5988
5989 uint64_t data = MemURead (context, address, 1, 0, &success);
5990 if (!success)
5991 return false;
5992
5993 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5994 return false;
5995
5996 // if wback then R[n] = offset_addr;
5997 if (wback)
5998 {
5999 context.type = eContextAdjustBaseRegister;
6000 context.SetAddress (offset_addr);
6001 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6002 return false;
6003 }
6004 }
6005 return true;
6006}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006007
6008// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6009// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6010// post-indexed, or pre-indexed addressing.
6011bool
6012EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6013{
6014#if 0
6015 if ConditionPassed() then
6016 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6017 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6018 address = if index then offset_addr else R[n];
6019 data = MemU[address,2];
6020 if wback then R[n] = offset_addr;
6021 if UnalignedSupport() || address<0> = ’0’ then
6022 R[t] = ZeroExtend(data, 32);
6023 else // Can only apply before ARMv7
6024 R[t] = bits(32) UNKNOWN;
6025#endif
6026
6027
6028 bool success = false;
6029 const uint32_t opcode = OpcodeAsUnsigned (&success);
6030 if (!success)
6031 return false;
6032
6033 if (ConditionPassed())
6034 {
6035 uint32_t t;
6036 uint32_t n;
6037 uint32_t imm32;
6038 bool index;
6039 bool add;
6040 bool wback;
6041
6042 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6043 switch (encoding)
6044 {
6045 case eEncodingT1:
6046 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6047 t = Bits32 (opcode, 2, 0);
6048 n = Bits32 (opcode, 5, 3);
6049 imm32 = Bits32 (opcode, 10, 6) << 1;
6050
6051 // index = TRUE; add = TRUE; wback = FALSE;
6052 index = true;
6053 add = true;
6054 wback = false;
6055
6056 break;
6057
6058 case eEncodingT2:
6059 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6060 // if Rn == ’1111’ then SEE LDRH (literal);
6061 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6062 t = Bits32 (opcode, 15, 12);
6063 n = Bits32 (opcode, 19, 16);
6064 imm32 = Bits32 (opcode, 11, 0);
6065
6066 // index = TRUE; add = TRUE; wback = FALSE;
6067 index = true;
6068 add = true;
6069 wback = false;
6070
6071 // if t == 13 then UNPREDICTABLE;
6072 if (t == 13)
6073 return false;
6074 break;
6075
6076 case eEncodingT3:
6077 // if Rn == ’1111’ then SEE LDRH (literal);
6078 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6079 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6080 // if P == ’0’ && W == ’0’ then UNDEFINED;
6081 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6082 return false;
6083
6084 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6085 t = Bits32 (opcode, 15, 12);
6086 n = Bits32 (opcode, 19, 16);
6087 imm32 = Bits32 (opcode, 7, 0);
6088
6089 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6090 index = BitIsSet (opcode, 10);
6091 add = BitIsSet (opcode, 9);
6092 wback = BitIsSet (opcode, 8);
6093
6094 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6095 if (BadReg (t) || (wback && (n == t)))
6096 return false;
6097 break;
6098
6099 default:
6100 return false;
6101 }
6102
6103 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6104 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6105 if (!success)
6106 return false;
6107
6108 addr_t offset_addr;
6109 addr_t address;
6110
6111 if (add)
6112 offset_addr = Rn + imm32;
6113 else
6114 offset_addr = Rn - imm32;
6115
6116 // address = if index then offset_addr else R[n];
6117 if (index)
6118 address = offset_addr;
6119 else
6120 address = Rn;
6121
6122 // data = MemU[address,2];
6123 Register base_reg;
6124 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6125
6126 EmulateInstruction::Context context;
6127 context.type = eContextRegisterLoad;
6128 context.SetRegisterPlusOffset (base_reg, address - Rn);
6129
6130 uint64_t data = MemURead (context, address, 2, 0, &success);
6131 if (!success)
6132 return false;
6133
6134 // if wback then R[n] = offset_addr;
6135 if (wback)
6136 {
6137 context.type = eContextAdjustBaseRegister;
6138 context.SetAddress (offset_addr);
6139 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6140 return false;
6141 }
6142
6143 // if UnalignedSupport() || address<0> = ’0’ then
6144 if (UnalignedSupport () || BitIsClear (address, 0))
6145 {
6146 // R[t] = ZeroExtend(data, 32);
6147 context.type = eContextRegisterLoad;
6148 context.SetRegisterPlusOffset (base_reg, address - Rn);
6149 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6150 return false;
6151 }
6152 else // Can only apply before ARMv7
6153 {
6154 // R[t] = bits(32) UNKNOWN;
6155 WriteBits32Unknown (t);
6156 }
6157 }
6158 return true;
6159}
Caroline Ticefe479112011-02-18 18:52:37 +00006160
Caroline Tice952b5382011-02-28 23:15:24 +00006161// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6162// zero-extends it to form a 32-bit word, and writes it to a register.
6163bool
6164EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6165{
6166#if 0
6167 if ConditionPassed() then
6168 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6169 base = Align(PC,4);
6170 address = if add then (base + imm32) else (base - imm32);
6171 data = MemU[address,2];
6172 if UnalignedSupport() || address<0> = ’0’ then
6173 R[t] = ZeroExtend(data, 32);
6174 else // Can only apply before ARMv7
6175 R[t] = bits(32) UNKNOWN;
6176#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006177
Caroline Tice952b5382011-02-28 23:15:24 +00006178 bool success = false;
6179 const uint32_t opcode = OpcodeAsUnsigned (&success);
6180 if (!success)
6181 return false;
6182
6183 if (ConditionPassed())
6184 {
6185 uint32_t t;
6186 uint32_t imm32;
6187 bool add;
6188
6189 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6190 switch (encoding)
6191 {
6192 case eEncodingT1:
6193 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6194 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6195 t = Bits32 (opcode, 15, 12);
6196 imm32 = Bits32 (opcode, 11, 0);
6197 add = BitIsSet (opcode, 23);
6198
6199 // if t == 13 then UNPREDICTABLE;
6200 if (t == 13)
6201 return false;
6202
6203 break;
6204
6205 case eEncodingA1:
6206 {
6207 uint32_t imm4H = Bits32 (opcode, 11, 8);
6208 uint32_t imm4L = Bits32 (opcode, 3, 0);
6209
6210 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6211 t = Bits32 (opcode, 15, 12);
6212 imm32 = (imm4H << 4) & imm4L;
6213 add = BitIsSet (opcode, 23);
6214
6215 // if t == 15 then UNPREDICTABLE;
6216 if (t == 15)
6217 return false;
6218 break;
6219 }
6220
6221 default:
6222 return false;
6223 }
6224
6225 // base = Align(PC,4);
6226 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6227 if (!success)
6228 return false;
6229
6230 addr_t base = AlignPC (pc_value);
6231 addr_t address;
6232
6233 // address = if add then (base + imm32) else (base - imm32);
6234 if (add)
6235 address = base + imm32;
6236 else
6237 address = base - imm32;
6238
6239 // data = MemU[address,2];
6240 Register base_reg;
6241 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6242
6243 EmulateInstruction::Context context;
6244 context.type = eContextRegisterLoad;
6245 context.SetRegisterPlusOffset (base_reg, address - base);
6246
6247 uint64_t data = MemURead (context, address, 2, 0, &success);
6248 if (!success)
6249 return false;
6250
6251
6252 // if UnalignedSupport() || address<0> = ’0’ then
6253 if (UnalignedSupport () || BitIsClear (address, 0))
6254 {
6255 // R[t] = ZeroExtend(data, 32);
6256 context.type = eContextRegisterLoad;
6257 context.SetRegisterPlusOffset (base_reg, address - base);
6258 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6259 return false;
6260
6261 }
6262 else // Can only apply before ARMv7
6263 {
6264 // R[t] = bits(32) UNKNOWN;
6265 WriteBits32Unknown (t);
6266 }
6267 }
6268 return true;
6269}
6270
Caroline Tice0e6bc952011-03-01 18:00:42 +00006271// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6272// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6273// be shifted left by 0, 1, 2, or 3 bits.
6274bool
6275EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6276{
6277#if 0
6278 if ConditionPassed() then
6279 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6280 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6281 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6282 address = if index then offset_addr else R[n];
6283 data = MemU[address,2];
6284 if wback then R[n] = offset_addr;
6285 if UnalignedSupport() || address<0> = ’0’ then
6286 R[t] = ZeroExtend(data, 32);
6287 else // Can only apply before ARMv7
6288 R[t] = bits(32) UNKNOWN;
6289#endif
6290
6291 bool success = false;
6292 const uint32_t opcode = OpcodeAsUnsigned (&success);
6293 if (!success)
6294 return false;
6295
6296 if (ConditionPassed())
6297 {
6298 uint32_t t;
6299 uint32_t n;
6300 uint32_t m;
6301 bool index;
6302 bool add;
6303 bool wback;
6304 ARM_ShifterType shift_t;
6305 uint32_t shift_n;
6306
6307 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6308 switch (encoding)
6309 {
6310 case eEncodingT1:
6311 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6312 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6313 t = Bits32 (opcode, 2, 0);
6314 n = Bits32 (opcode, 5, 3);
6315 m = Bits32 (opcode, 8, 6);
6316
6317 // index = TRUE; add = TRUE; wback = FALSE;
6318 index = true;
6319 add = true;
6320 wback = false;
6321
6322 // (shift_t, shift_n) = (SRType_LSL, 0);
6323 shift_t = SRType_LSL;
6324 shift_n = 0;
6325
6326 break;
6327
6328 case eEncodingT2:
6329 // if Rn == ’1111’ then SEE LDRH (literal);
6330 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6331 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6332 t = Bits32 (opcode, 15, 12);
6333 n = Bits32 (opcode, 19, 16);
6334 m = Bits32 (opcode, 3, 0);
6335
6336 // index = TRUE; add = TRUE; wback = FALSE;
6337 index = true;
6338 add = true;
6339 wback = false;
6340
6341 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6342 shift_t = SRType_LSL;
6343 shift_n = Bits32 (opcode, 5, 4);
6344
6345 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6346 if ((t == 13) || BadReg (m))
6347 return false;
6348 break;
6349
6350 case eEncodingA1:
6351 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6352 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6353 t = Bits32 (opcode, 15, 12);
6354 n = Bits32 (opcode, 19, 16);
6355 m = Bits32 (opcode, 3, 0);
6356
6357 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6358 index = BitIsSet (opcode, 24);
6359 add = BitIsSet (opcode, 23);
6360 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6361
6362 // (shift_t, shift_n) = (SRType_LSL, 0);
6363 shift_t = SRType_LSL;
6364 shift_n = 0;
6365
6366 // if t == 15 || m == 15 then UNPREDICTABLE;
6367 if ((t == 15) || (m == 15))
6368 return false;
6369
6370 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6371 if (wback && ((n == 15) || (n == t)))
6372 return false;
6373
6374 break;
6375
6376 default:
6377 return false;
6378 }
6379
6380 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6381
6382 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6383 if (!success)
6384 return false;
6385
6386 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6387
6388 addr_t offset_addr;
6389 addr_t address;
6390
6391 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6392 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6393 if (!success)
6394 return false;
6395
6396 if (add)
6397 offset_addr = Rn + offset;
6398 else
6399 offset_addr = Rn - offset;
6400
6401 // address = if index then offset_addr else R[n];
6402 if (index)
6403 address = offset_addr;
6404 else
6405 address = Rn;
6406
6407 // data = MemU[address,2];
6408 Register base_reg;
6409 Register offset_reg;
6410 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6411 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6412
6413 EmulateInstruction::Context context;
6414 context.type = eContextRegisterLoad;
6415 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6416 uint64_t data = MemURead (context, address, 2, 0, &success);
6417 if (!success)
6418 return false;
6419
6420 // if wback then R[n] = offset_addr;
6421 if (wback)
6422 {
6423 context.type = eContextAdjustBaseRegister;
6424 context.SetAddress (offset_addr);
6425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6426 return false;
6427 }
6428
6429 // if UnalignedSupport() || address<0> = ’0’ then
6430 if (UnalignedSupport() || BitIsClear (address, 0))
6431 {
6432 // R[t] = ZeroExtend(data, 32);
6433 context.type = eContextRegisterLoad;
6434 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6436 return false;
6437 }
6438 else // Can only apply before ARMv7
6439 {
6440 // R[t] = bits(32) UNKNOWN;
6441 WriteBits32Unknown (t);
6442 }
6443 }
6444 return true;
6445}
6446
Caroline Ticea5e28af2011-03-01 21:53:03 +00006447// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6448// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6449// or pre-indexed addressing.
6450bool
6451EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6452{
6453#if 0
6454 if ConditionPassed() then
6455 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6456 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6457 address = if index then offset_addr else R[n];
6458 R[t] = SignExtend(MemU[address,1], 32);
6459 if wback then R[n] = offset_addr;
6460#endif
6461
6462 bool success = false;
6463 const uint32_t opcode = OpcodeAsUnsigned (&success);
6464 if (!success)
6465 return false;
6466
6467 if (ConditionPassed ())
6468 {
6469 uint32_t t;
6470 uint32_t n;
6471 uint32_t imm32;
6472 bool index;
6473 bool add;
6474 bool wback;
6475
6476 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6477 switch (encoding)
6478 {
6479 case eEncodingT1:
6480 // if Rt == ’1111’ then SEE PLI;
6481 // if Rn == ’1111’ then SEE LDRSB (literal);
6482 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6483 t = Bits32 (opcode, 15, 12);
6484 n = Bits32 (opcode, 19, 16);
6485 imm32 = Bits32 (opcode, 11, 0);
6486
6487 // index = TRUE; add = TRUE; wback = FALSE;
6488 index = true;
6489 add = true;
6490 wback = false;
6491
6492 // if t == 13 then UNPREDICTABLE;
6493 if (t == 13)
6494 return false;
6495
6496 break;
6497
6498 case eEncodingT2:
6499 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6500 // if Rn == ’1111’ then SEE LDRSB (literal);
6501 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6502 // if P == ’0’ && W == ’0’ then UNDEFINED;
6503 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6504 return false;
6505
6506 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6507 t = Bits32 (opcode, 15, 12);
6508 n = Bits32 (opcode, 19, 16);
6509 imm32 = Bits32 (opcode, 7, 0);
6510
6511 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6512 index = BitIsSet (opcode, 10);
6513 add = BitIsSet (opcode, 9);
6514 wback = BitIsSet (opcode, 8);
6515
6516 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6517 if (BadReg (t) || (wback && (n == t)))
6518 return false;
6519
6520 break;
6521
6522 case eEncodingA1:
6523 {
6524 // if Rn == ’1111’ then SEE LDRSB (literal);
6525 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6526 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6527 t = Bits32 (opcode, 15, 12);
6528 n = Bits32 (opcode, 19, 16);
6529
6530 uint32_t imm4H = Bits32 (opcode, 11, 8);
6531 uint32_t imm4L = Bits32 (opcode, 3, 0);
6532 imm32 = (imm4H << 4) & imm4L;
6533
6534 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6535 index = BitIsSet (opcode, 24);
6536 add = BitIsSet (opcode, 23);
6537 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6538
6539 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6540 if ((t == 15) || (wback && (n == t)))
6541 return false;
6542
6543 break;
6544 }
6545
6546 default:
6547 return false;
6548 }
6549
6550 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6551 if (!success)
6552 return false;
6553
6554 addr_t offset_addr;
6555 addr_t address;
6556
6557 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6558 if (add)
6559 offset_addr = Rn + imm32;
6560 else
6561 offset_addr = Rn - imm32;
6562
6563 // address = if index then offset_addr else R[n];
6564 if (index)
6565 address = offset_addr;
6566 else
6567 address = Rn;
6568
6569 // R[t] = SignExtend(MemU[address,1], 32);
6570 Register base_reg;
6571 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6572
6573 EmulateInstruction::Context context;
6574 context.type = eContextRegisterLoad;
6575 context.SetRegisterPlusOffset (base_reg, address - Rn);
6576
6577 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6578 if (!success)
6579 return false;
6580
6581 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6582 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6583 return false;
6584
6585 // if wback then R[n] = offset_addr;
6586 if (wback)
6587 {
6588 context.type = eContextAdjustBaseRegister;
6589 context.SetAddress (offset_addr);
6590 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6591 return false;
6592 }
6593 }
6594
6595 return true;
6596}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006597
Caroline Tice5f593912011-03-01 22:25:17 +00006598// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6599// sign-extends it to form a 32-bit word, and writes tit to a register.
6600bool
6601EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6602{
6603#if 0
6604 if ConditionPassed() then
6605 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6606 base = Align(PC,4);
6607 address = if add then (base + imm32) else (base - imm32);
6608 R[t] = SignExtend(MemU[address,1], 32);
6609#endif
6610
6611 bool success = false;
6612 const uint32_t opcode = OpcodeAsUnsigned (&success);
6613 if (!success)
6614 return false;
6615
6616 if (ConditionPassed ())
6617 {
6618 uint32_t t;
6619 uint32_t imm32;
6620 bool add;
6621
6622 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6623 switch (encoding)
6624 {
6625 case eEncodingT1:
6626 // if Rt == ’1111’ then SEE PLI;
6627 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6628 t = Bits32 (opcode, 15, 12);
6629 imm32 = Bits32 (opcode, 11, 0);
6630 add = BitIsSet (opcode, 23);
6631
6632 // if t == 13 then UNPREDICTABLE;
6633 if (t == 13)
6634 return false;
6635
6636 break;
6637
6638 case eEncodingA1:
6639 {
6640 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6641 t = Bits32 (opcode, 15, 12);
6642 uint32_t imm4H = Bits32 (opcode, 11, 8);
6643 uint32_t imm4L = Bits32 (opcode, 3, 0);
6644 imm32 = (imm4H << 4) & imm4L;
6645 add = BitIsSet (opcode, 23);
6646
6647 // if t == 15 then UNPREDICTABLE;
6648 if (t == 15)
6649 return false;
6650
6651 break;
6652 }
6653
6654 default:
6655 return false;
6656 }
6657
6658 // base = Align(PC,4);
6659 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6660 &success);
6661 if (!success)
6662 return false;
6663 uint64_t base = AlignPC (pc_value);
6664
6665 // address = if add then (base + imm32) else (base - imm32);
6666 addr_t address;
6667 if (add)
6668 address = base + imm32;
6669 else
6670 address = base - imm32;
6671
6672 // R[t] = SignExtend(MemU[address,1], 32);
6673 Register base_reg;
6674 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6675
6676 EmulateInstruction::Context context;
6677 context.type = eContextRegisterLoad;
6678 context.SetRegisterPlusOffset (base_reg, address - base);
6679
6680 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6681 if (!success)
6682 return false;
6683
6684 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6685 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6686 return false;
6687 }
6688 return true;
6689}
6690
Caroline Tice672f3112011-03-01 23:55:59 +00006691// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6692// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6693// shifted left by 0, 1, 2, or 3 bits.
6694bool
6695EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
6696{
6697#if 0
6698 if ConditionPassed() then
6699 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6700 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6701 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6702 address = if index then offset_addr else R[n];
6703 R[t] = SignExtend(MemU[address,1], 32);
6704 if wback then R[n] = offset_addr;
6705#endif
6706
6707 bool success = false;
6708 const uint32_t opcode = OpcodeAsUnsigned (&success);
6709 if (!success)
6710 return false;
6711
6712 if (ConditionPassed ())
6713 {
6714 uint32_t t;
6715 uint32_t n;
6716 uint32_t m;
6717 bool index;
6718 bool add;
6719 bool wback;
6720 ARM_ShifterType shift_t;
6721 uint32_t shift_n;
6722
6723 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6724 switch (encoding)
6725 {
6726 case eEncodingT1:
6727 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6728 t = Bits32 (opcode, 2, 0);
6729 n = Bits32 (opcode, 5, 3);
6730 m = Bits32 (opcode, 8, 6);
6731
6732 // index = TRUE; add = TRUE; wback = FALSE;
6733 index = true;
6734 add = true;
6735 wback = false;
6736
6737 // (shift_t, shift_n) = (SRType_LSL, 0);
6738 shift_t = SRType_LSL;
6739 shift_n = 0;
6740
6741 break;
6742
6743 case eEncodingT2:
6744 // if Rt == ’1111’ then SEE PLI;
6745 // if Rn == ’1111’ then SEE LDRSB (literal);
6746 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6747 t = Bits32 (opcode, 15, 12);
6748 n = Bits32 (opcode, 19, 16);
6749 m = Bits32 (opcode, 3, 0);
6750
6751 // index = TRUE; add = TRUE; wback = FALSE;
6752 index = true;
6753 add = true;
6754 wback = false;
6755
6756 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6757 shift_t = SRType_LSL;
6758 shift_n = Bits32 (opcode, 5, 4);
6759
6760 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6761 if ((t == 13) || BadReg (m))
6762 return false;
6763 break;
6764
6765 case eEncodingA1:
6766 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6767 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6768 t = Bits32 (opcode, 15, 12);
6769 n = Bits32 (opcode, 19, 16);
6770 m = Bits32 (opcode, 3, 0);
6771
6772 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6773 index = BitIsSet (opcode, 24);
6774 add = BitIsSet (opcode, 23);
6775 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6776
6777 // (shift_t, shift_n) = (SRType_LSL, 0);
6778 shift_t = SRType_LSL;
6779 shift_n = 0;
6780
6781 // if t == 15 || m == 15 then UNPREDICTABLE;
6782 if ((t == 15) || (m == 15))
6783 return false;
6784
6785 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6786 if (wback && ((n == 15) || (n == t)))
6787 return false;
6788 break;
6789
6790 default:
6791 return false;
6792 }
6793
6794 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6795 if (!success)
6796 return false;
6797
6798 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6799 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6800
6801 addr_t offset_addr;
6802 addr_t address;
6803
6804 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6805 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6806 if (!success)
6807 return false;
6808
6809 if (add)
6810 offset_addr = Rn + offset;
6811 else
6812 offset_addr = Rn - offset;
6813
6814 // address = if index then offset_addr else R[n];
6815 if (index)
6816 address = offset_addr;
6817 else
6818 address = Rn;
6819
6820 // R[t] = SignExtend(MemU[address,1], 32);
6821 Register base_reg;
6822 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6823 Register offset_reg;
6824 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6825
6826 EmulateInstruction::Context context;
6827 context.type = eContextRegisterLoad;
6828 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6829
6830 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6831 if (!success)
6832 return false;
6833
6834 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6835 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6836 return false;
6837
6838 // if wback then R[n] = offset_addr;
6839 if (wback)
6840 {
6841 context.type = eContextAdjustBaseRegister;
6842 context.SetAddress (offset_addr);
6843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6844 return false;
6845 }
6846 }
6847 return true;
6848}
6849
Caroline Tice78fb5632011-03-02 00:39:42 +00006850// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
6851// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
6852// pre-indexed addressing.
6853bool
6854EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
6855{
6856#if 0
6857 if ConditionPassed() then
6858 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6859 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6860 address = if index then offset_addr else R[n];
6861 data = MemU[address,2];
6862 if wback then R[n] = offset_addr;
6863 if UnalignedSupport() || address<0> = ’0’ then
6864 R[t] = SignExtend(data, 32);
6865 else // Can only apply before ARMv7
6866 R[t] = bits(32) UNKNOWN;
6867#endif
6868
6869 bool success = false;
6870 const uint32_t opcode = OpcodeAsUnsigned (&success);
6871 if (!success)
6872 return false;
6873
6874 if (ConditionPassed())
6875 {
6876 uint32_t t;
6877 uint32_t n;
6878 uint32_t imm32;
6879 bool index;
6880 bool add;
6881 bool wback;
6882
6883 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6884 switch (encoding)
6885 {
6886 case eEncodingT1:
6887 // if Rn == ’1111’ then SEE LDRSH (literal);
6888 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6889 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6890 t = Bits32 (opcode, 15, 12);
6891 n = Bits32 (opcode, 19, 16);
6892 imm32 = Bits32 (opcode, 11, 0);
6893
6894 // index = TRUE; add = TRUE; wback = FALSE;
6895 index = true;
6896 add = true;
6897 wback = false;
6898
6899 // if t == 13 then UNPREDICTABLE;
6900 if (t == 13)
6901 return false;
6902
6903 break;
6904
6905 case eEncodingT2:
6906 // if Rn == ’1111’ then SEE LDRSH (literal);
6907 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6908 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
6909 // if P == ’0’ && W == ’0’ then UNDEFINED;
6910 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6911 return false;
6912
6913 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6914 t = Bits32 (opcode, 15, 12);
6915 n = Bits32 (opcode, 19, 16);
6916 imm32 = Bits32 (opcode, 7, 0);
6917
6918 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6919 index = BitIsSet (opcode, 10);
6920 add = BitIsSet (opcode, 9);
6921 wback = BitIsSet (opcode, 8);
6922
6923 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6924 if (BadReg (t) || (wback && (n == t)))
6925 return false;
6926
6927 break;
6928
6929 case eEncodingA1:
6930 {
6931 // if Rn == ’1111’ then SEE LDRSH (literal);
6932 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
6933 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6934 t = Bits32 (opcode, 15, 12);
6935 n = Bits32 (opcode, 19, 16);
6936 uint32_t imm4H = Bits32 (opcode, 11,8);
6937 uint32_t imm4L = Bits32 (opcode, 3, 0);
6938 imm32 = (imm4H << 4) & imm4L;
6939
6940 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6941 index = BitIsSet (opcode, 24);
6942 add = BitIsSet (opcode, 23);
6943 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6944
6945 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6946 if ((t == 15) || (wback && (n == t)))
6947 return false;
6948
6949 break;
6950 }
6951
6952 default:
6953 return false;
6954 }
6955
6956 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6957 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6958 if (!success)
6959 return false;
6960
6961 addr_t offset_addr;
6962 if (add)
6963 offset_addr = Rn + imm32;
6964 else
6965 offset_addr = Rn - imm32;
6966
6967 // address = if index then offset_addr else R[n];
6968 addr_t address;
6969 if (index)
6970 address = offset_addr;
6971 else
6972 address = Rn;
6973
6974 // data = MemU[address,2];
6975 Register base_reg;
6976 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6977
6978 EmulateInstruction::Context context;
6979 context.type = eContextRegisterLoad;
6980 context.SetRegisterPlusOffset (base_reg, address - Rn);
6981
6982 uint64_t data = MemURead (context, address, 2, 0, &success);
6983 if (!success)
6984 return false;
6985
6986 // if wback then R[n] = offset_addr;
6987 if (wback)
6988 {
6989 context.type = eContextAdjustBaseRegister;
6990 context.SetAddress (offset_addr);
6991 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6992 return false;
6993 }
6994
6995 // if UnalignedSupport() || address<0> = ’0’ then
6996 if (UnalignedSupport() || BitIsClear (address, 0))
6997 {
6998 // R[t] = SignExtend(data, 32);
6999 int64_t signed_data = llvm::SignExtend64<16>(data);
7000 context.type = eContextRegisterLoad;
7001 context.SetRegisterPlusOffset (base_reg, address - Rn);
7002 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7003 return false;
7004 }
7005 else // Can only apply before ARMv7
7006 {
7007 // R[t] = bits(32) UNKNOWN;
7008 WriteBits32Unknown (t);
7009 }
7010 }
7011 return true;
7012}
7013
Caroline Ticed2fac092011-03-02 19:45:34 +00007014// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7015// sign-extends it to from a 32-bit word, and writes it to a register.
7016bool
7017EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7018{
7019#if 0
7020 if ConditionPassed() then
7021 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7022 base = Align(PC,4);
7023 address = if add then (base + imm32) else (base - imm32);
7024 data = MemU[address,2];
7025 if UnalignedSupport() || address<0> = ’0’ then
7026 R[t] = SignExtend(data, 32);
7027 else // Can only apply before ARMv7
7028 R[t] = bits(32) UNKNOWN;
7029#endif
7030
7031 bool success = false;
7032 const uint32_t opcode = OpcodeAsUnsigned (&success);
7033 if (!success)
7034 return false;
7035
7036 if (ConditionPassed())
7037 {
7038 uint32_t t;
7039 uint32_t imm32;
7040 bool add;
7041
7042 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7043 switch (encoding)
7044 {
7045 case eEncodingT1:
7046 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7047 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7048 t = Bits32 (opcode, 15, 12);
7049 imm32 = Bits32 (opcode, 11, 0);
7050 add = BitIsSet (opcode, 23);
7051
7052 // if t == 13 then UNPREDICTABLE;
7053 if (t == 13)
7054 return false;
7055
7056 break;
7057
7058 case eEncodingA1:
7059 {
7060 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7061 t = Bits32 (opcode, 15, 12);
7062 uint32_t imm4H = Bits32 (opcode, 11, 8);
7063 uint32_t imm4L = Bits32 (opcode, 3, 0);
7064 imm32 = (imm4H << 4) & imm4L;
7065 add = BitIsSet (opcode, 23);
7066
7067 // if t == 15 then UNPREDICTABLE;
7068 if (t == 15)
7069 return false;
7070
7071 break;
7072 }
7073 default:
7074 return false;
7075 }
7076
7077 // base = Align(PC,4);
7078 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
7079 if (!success)
7080 return false;
7081
7082 uint64_t base = AlignPC (pc_value);
7083
7084 addr_t address;
7085 // address = if add then (base + imm32) else (base - imm32);
7086 if (add)
7087 address = base + imm32;
7088 else
7089 address = base - imm32;
7090
7091 // data = MemU[address,2];
7092 Register base_reg;
7093 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7094
7095 EmulateInstruction::Context context;
7096 context.type = eContextRegisterLoad;
7097 context.SetRegisterPlusOffset (base_reg, imm32);
7098
7099 uint64_t data = MemURead (context, address, 2, 0, &success);
7100 if (!success)
7101 return false;
7102
7103 // if UnalignedSupport() || address<0> = ’0’ then
7104 if (UnalignedSupport() || BitIsClear (address, 0))
7105 {
7106 // R[t] = SignExtend(data, 32);
7107 int64_t signed_data = llvm::SignExtend64<16>(data);
7108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7109 return false;
7110 }
7111 else // Can only apply before ARMv7
7112 {
7113 // R[t] = bits(32) UNKNOWN;
7114 WriteBits32Unknown (t);
7115 }
7116 }
7117 return true;
7118}
7119
Caroline Tice291a3e92011-03-02 21:13:44 +00007120// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7121// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7122// shifted left by 0, 1, 2, or 3 bits.
7123bool
7124EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7125{
7126#if 0
7127 if ConditionPassed() then
7128 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7129 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7130 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7131 address = if index then offset_addr else R[n];
7132 data = MemU[address,2];
7133 if wback then R[n] = offset_addr;
7134 if UnalignedSupport() || address<0> = ’0’ then
7135 R[t] = SignExtend(data, 32);
7136 else // Can only apply before ARMv7
7137 R[t] = bits(32) UNKNOWN;
7138#endif
7139
7140 bool success = false;
7141 const uint32_t opcode = OpcodeAsUnsigned (&success);
7142 if (!success)
7143 return false;
7144
7145 if (ConditionPassed())
7146 {
7147 uint32_t t;
7148 uint32_t n;
7149 uint32_t m;
7150 bool index;
7151 bool add;
7152 bool wback;
7153 ARM_ShifterType shift_t;
7154 uint32_t shift_n;
7155
7156 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7157 switch (encoding)
7158 {
7159 case eEncodingT1:
7160 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7161 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7162 t = Bits32 (opcode, 2, 0);
7163 n = Bits32 (opcode, 5, 3);
7164 m = Bits32 (opcode, 8, 6);
7165
7166 // index = TRUE; add = TRUE; wback = FALSE;
7167 index = true;
7168 add = true;
7169 wback = false;
7170
7171 // (shift_t, shift_n) = (SRType_LSL, 0);
7172 shift_t = SRType_LSL;
7173 shift_n = 0;
7174
7175 break;
7176
7177 case eEncodingT2:
7178 // if Rn == ’1111’ then SEE LDRSH (literal);
7179 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7180 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7181 t = Bits32 (opcode, 15, 12);
7182 n = Bits32 (opcode, 19, 16);
7183 m = Bits32 (opcode, 3, 0);
7184
7185 // index = TRUE; add = TRUE; wback = FALSE;
7186 index = true;
7187 add = true;
7188 wback = false;
7189
7190 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7191 shift_t = SRType_LSL;
7192 shift_n = Bits32 (opcode, 5, 4);
7193
7194 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7195 if ((t == 13) || BadReg (m))
7196 return false;
7197
7198 break;
7199
7200 case eEncodingA1:
7201 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7202 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7203 t = Bits32 (opcode, 15, 12);
7204 n = Bits32 (opcode, 19, 16);
7205 m = Bits32 (opcode, 3, 0);
7206
7207 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7208 index = BitIsSet (opcode, 24);
7209 add = BitIsSet (opcode, 23);
7210 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7211
7212 // (shift_t, shift_n) = (SRType_LSL, 0);
7213 shift_t = SRType_LSL;
7214 shift_n = 0;
7215
7216 // if t == 15 || m == 15 then UNPREDICTABLE;
7217 if ((t == 15) || (m == 15))
7218 return false;
7219
7220 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7221 if (wback && ((n == 15) || (n == t)))
7222 return false;
7223
7224 break;
7225
7226 default:
7227 break;
7228 }
7229
7230 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7231 if (!success)
7232 return false;
7233
7234 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7235 if (!success)
7236 return false;
7237
7238 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7239 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7240
7241 addr_t offset_addr;
7242 addr_t address;
7243
7244 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7245 if (add)
7246 offset_addr = Rn + offset;
7247 else
7248 offset_addr = Rn - offset;
7249
7250 // address = if index then offset_addr else R[n];
7251 if (index)
7252 address = offset_addr;
7253 else
7254 address = Rn;
7255
7256 // data = MemU[address,2];
7257 Register base_reg;
7258 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7259
7260 Register offset_reg;
7261 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7262
7263 EmulateInstruction::Context context;
7264 context.type = eContextRegisterLoad;
7265 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7266
7267 uint64_t data = MemURead (context, address, 2, 0, &success);
7268 if (!success)
7269 return false;
7270
7271 // if wback then R[n] = offset_addr;
7272 if (wback)
7273 {
7274 context.type = eContextAdjustBaseRegister;
7275 context.SetAddress (offset_addr);
7276 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7277 return false;
7278 }
7279
7280 // if UnalignedSupport() || address<0> = ’0’ then
7281 if (UnalignedSupport() || BitIsClear (address, 0))
7282 {
7283 // R[t] = SignExtend(data, 32);
7284 context.type = eContextRegisterLoad;
7285 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7286
7287 int64_t signed_data = llvm::SignExtend64<16>(data);
7288 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7289 return false;
7290 }
7291 else // Can only apply before ARMv7
7292 {
7293 // R[t] = bits(32) UNKNOWN;
7294 WriteBits32Unknown (t);
7295 }
7296 }
7297 return true;
7298}
7299
Johnny Chen2115b412011-02-21 23:42:44 +00007300// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7301// and writes the result to the destination register. It can optionally update the condition flags based on
7302// the result.
7303bool
7304EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
7305{
7306#if 0
7307 // ARM pseudo code...
7308 if ConditionPassed() then
7309 EncodingSpecificOperations();
7310 result = R[n] EOR imm32;
7311 if d == 15 then // Can only occur for ARM encoding
7312 ALUWritePC(result); // setflags is always FALSE here
7313 else
7314 R[d] = result;
7315 if setflags then
7316 APSR.N = result<31>;
7317 APSR.Z = IsZeroBit(result);
7318 APSR.C = carry;
7319 // APSR.V unchanged
7320#endif
7321
7322 bool success = false;
7323 const uint32_t opcode = OpcodeAsUnsigned (&success);
7324 if (!success)
7325 return false;
7326
7327 if (ConditionPassed())
7328 {
7329 uint32_t Rd, Rn;
7330 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7331 bool setflags;
7332 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7333 switch (encoding)
7334 {
7335 case eEncodingT1:
7336 Rd = Bits32(opcode, 11, 8);
7337 Rn = Bits32(opcode, 19, 16);
7338 setflags = BitIsSet(opcode, 20);
7339 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7340 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7341 if (Rd == 15 && setflags)
7342 return EmulateTEQImm(eEncodingT1);
7343 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7344 return false;
7345 break;
7346 case eEncodingA1:
7347 Rd = Bits32(opcode, 15, 12);
7348 Rn = Bits32(opcode, 19, 16);
7349 setflags = BitIsSet(opcode, 20);
7350 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7351 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7352 // TODO: Emulate SUBS PC, LR and related instructions.
7353 if (Rd == 15 && setflags)
7354 return false;
7355 break;
7356 default:
7357 return false;
7358 }
7359
7360 // Read the first operand.
7361 uint32_t val1 = ReadCoreReg(Rn, &success);
7362 if (!success)
7363 return false;
7364
7365 uint32_t result = val1 ^ imm32;
7366
7367 EmulateInstruction::Context context;
7368 context.type = EmulateInstruction::eContextImmediate;
7369 context.SetNoArgs ();
7370
7371 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7372 return false;
7373 }
7374 return true;
7375}
7376
7377// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7378// optionally-shifted register value, and writes the result to the destination register.
7379// It can optionally update the condition flags based on the result.
7380bool
7381EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7382{
7383#if 0
7384 // ARM pseudo code...
7385 if ConditionPassed() then
7386 EncodingSpecificOperations();
7387 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7388 result = R[n] EOR shifted;
7389 if d == 15 then // Can only occur for ARM encoding
7390 ALUWritePC(result); // setflags is always FALSE here
7391 else
7392 R[d] = result;
7393 if setflags then
7394 APSR.N = result<31>;
7395 APSR.Z = IsZeroBit(result);
7396 APSR.C = carry;
7397 // APSR.V unchanged
7398#endif
7399
7400 bool success = false;
7401 const uint32_t opcode = OpcodeAsUnsigned (&success);
7402 if (!success)
7403 return false;
7404
7405 if (ConditionPassed())
7406 {
7407 uint32_t Rd, Rn, Rm;
7408 ARM_ShifterType shift_t;
7409 uint32_t shift_n; // the shift applied to the value read from Rm
7410 bool setflags;
7411 uint32_t carry;
7412 switch (encoding)
7413 {
7414 case eEncodingT1:
7415 Rd = Rn = Bits32(opcode, 2, 0);
7416 Rm = Bits32(opcode, 5, 3);
7417 setflags = !InITBlock();
7418 shift_t = SRType_LSL;
7419 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007420 break;
Johnny Chen2115b412011-02-21 23:42:44 +00007421 case eEncodingT2:
7422 Rd = Bits32(opcode, 11, 8);
7423 Rn = Bits32(opcode, 19, 16);
7424 Rm = Bits32(opcode, 3, 0);
7425 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007426 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7427 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00007428 if (Rd == 15 && setflags)
7429 return EmulateTEQReg(eEncodingT1);
7430 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
7431 return false;
7432 break;
7433 case eEncodingA1:
7434 Rd = Bits32(opcode, 15, 12);
7435 Rn = Bits32(opcode, 19, 16);
7436 Rm = Bits32(opcode, 3, 0);
7437 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007438 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007439 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7440 // TODO: Emulate SUBS PC, LR and related instructions.
7441 if (Rd == 15 && setflags)
7442 return false;
7443 break;
7444 default:
7445 return false;
7446 }
7447
7448 // Read the first operand.
7449 uint32_t val1 = ReadCoreReg(Rn, &success);
7450 if (!success)
7451 return false;
7452
7453 // Read the second operand.
7454 uint32_t val2 = ReadCoreReg(Rm, &success);
7455 if (!success)
7456 return false;
7457
7458 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7459 uint32_t result = val1 ^ shifted;
7460
7461 EmulateInstruction::Context context;
7462 context.type = EmulateInstruction::eContextImmediate;
7463 context.SetNoArgs ();
7464
7465 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7466 return false;
7467 }
7468 return true;
7469}
7470
Johnny Chen7c5234d2011-02-18 23:41:11 +00007471// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
7472// writes the result to the destination register. It can optionally update the condition flags based
7473// on the result.
7474bool
7475EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
7476{
7477#if 0
7478 // ARM pseudo code...
7479 if ConditionPassed() then
7480 EncodingSpecificOperations();
7481 result = R[n] OR imm32;
7482 if d == 15 then // Can only occur for ARM encoding
7483 ALUWritePC(result); // setflags is always FALSE here
7484 else
7485 R[d] = result;
7486 if setflags then
7487 APSR.N = result<31>;
7488 APSR.Z = IsZeroBit(result);
7489 APSR.C = carry;
7490 // APSR.V unchanged
7491#endif
7492
7493 bool success = false;
7494 const uint32_t opcode = OpcodeAsUnsigned (&success);
7495 if (!success)
7496 return false;
7497
7498 if (ConditionPassed())
7499 {
7500 uint32_t Rd, Rn;
7501 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7502 bool setflags;
7503 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7504 switch (encoding)
7505 {
7506 case eEncodingT1:
7507 Rd = Bits32(opcode, 11, 8);
7508 Rn = Bits32(opcode, 19, 16);
7509 setflags = BitIsSet(opcode, 20);
7510 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7511 // if Rn == ‘1111’ then SEE MOV (immediate);
7512 if (Rn == 15)
7513 return EmulateMOVRdImm(eEncodingT2);
7514 if (BadReg(Rd) || Rn == 13)
7515 return false;
7516 break;
7517 case eEncodingA1:
7518 Rd = Bits32(opcode, 15, 12);
7519 Rn = Bits32(opcode, 19, 16);
7520 setflags = BitIsSet(opcode, 20);
7521 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7522 // TODO: Emulate SUBS PC, LR and related instructions.
7523 if (Rd == 15 && setflags)
7524 return false;
7525 break;
7526 default:
7527 return false;
7528 }
7529
7530 // Read the first operand.
7531 uint32_t val1 = ReadCoreReg(Rn, &success);
7532 if (!success)
7533 return false;
7534
7535 uint32_t result = val1 | imm32;
7536
7537 EmulateInstruction::Context context;
7538 context.type = EmulateInstruction::eContextImmediate;
7539 context.SetNoArgs ();
7540
7541 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7542 return false;
7543 }
7544 return true;
7545}
7546
7547// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
7548// value, and writes the result to the destination register. It can optionally update the condition flags based
7549// on the result.
7550bool
7551EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
7552{
7553#if 0
7554 // ARM pseudo code...
7555 if ConditionPassed() then
7556 EncodingSpecificOperations();
7557 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7558 result = R[n] OR shifted;
7559 if d == 15 then // Can only occur for ARM encoding
7560 ALUWritePC(result); // setflags is always FALSE here
7561 else
7562 R[d] = result;
7563 if setflags then
7564 APSR.N = result<31>;
7565 APSR.Z = IsZeroBit(result);
7566 APSR.C = carry;
7567 // APSR.V unchanged
7568#endif
7569
7570 bool success = false;
7571 const uint32_t opcode = OpcodeAsUnsigned (&success);
7572 if (!success)
7573 return false;
7574
7575 if (ConditionPassed())
7576 {
7577 uint32_t Rd, Rn, Rm;
7578 ARM_ShifterType shift_t;
7579 uint32_t shift_n; // the shift applied to the value read from Rm
7580 bool setflags;
7581 uint32_t carry;
7582 switch (encoding)
7583 {
7584 case eEncodingT1:
7585 Rd = Rn = Bits32(opcode, 2, 0);
7586 Rm = Bits32(opcode, 5, 3);
7587 setflags = !InITBlock();
7588 shift_t = SRType_LSL;
7589 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007590 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007591 case eEncodingT2:
7592 Rd = Bits32(opcode, 11, 8);
7593 Rn = Bits32(opcode, 19, 16);
7594 Rm = Bits32(opcode, 3, 0);
7595 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007596 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7597 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007598 if (Rn == 15)
7599 return EmulateMOVRdRm(eEncodingT3);
7600 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
7601 return false;
7602 break;
7603 case eEncodingA1:
7604 Rd = Bits32(opcode, 15, 12);
7605 Rn = Bits32(opcode, 19, 16);
7606 Rm = Bits32(opcode, 3, 0);
7607 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007608 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007609 // TODO: Emulate SUBS PC, LR and related instructions.
7610 if (Rd == 15 && setflags)
7611 return false;
7612 break;
7613 default:
7614 return false;
7615 }
7616
7617 // Read the first operand.
7618 uint32_t val1 = ReadCoreReg(Rn, &success);
7619 if (!success)
7620 return false;
7621
7622 // Read the second operand.
7623 uint32_t val2 = ReadCoreReg(Rm, &success);
7624 if (!success)
7625 return false;
7626
7627 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00007628 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007629
7630 EmulateInstruction::Context context;
7631 context.type = EmulateInstruction::eContextImmediate;
7632 context.SetNoArgs ();
7633
7634 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7635 return false;
7636 }
7637 return true;
7638}
7639
Johnny Chened32e7c2011-02-22 23:42:58 +00007640// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
7641// the destination register. It can optionally update the condition flags based on the result.
7642bool
7643EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
7644{
7645#if 0
7646 // ARM pseudo code...
7647 if ConditionPassed() then
7648 EncodingSpecificOperations();
7649 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
7650 if d == 15 then // Can only occur for ARM encoding
7651 ALUWritePC(result); // setflags is always FALSE here
7652 else
7653 R[d] = result;
7654 if setflags then
7655 APSR.N = result<31>;
7656 APSR.Z = IsZeroBit(result);
7657 APSR.C = carry;
7658 APSR.V = overflow;
7659#endif
7660
7661 bool success = false;
7662 const uint32_t opcode = OpcodeAsUnsigned (&success);
7663 if (!success)
7664 return false;
7665
7666 uint32_t Rd; // the destination register
7667 uint32_t Rn; // the first operand
7668 bool setflags;
7669 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7670 switch (encoding) {
7671 case eEncodingT1:
7672 Rd = Bits32(opcode, 2, 0);
7673 Rn = Bits32(opcode, 5, 3);
7674 setflags = !InITBlock();
7675 imm32 = 0;
7676 break;
7677 case eEncodingT2:
7678 Rd = Bits32(opcode, 11, 8);
7679 Rn = Bits32(opcode, 19, 16);
7680 setflags = BitIsSet(opcode, 20);
7681 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7682 if (BadReg(Rd) || BadReg(Rn))
7683 return false;
7684 break;
7685 case eEncodingA1:
7686 Rd = Bits32(opcode, 15, 12);
7687 Rn = Bits32(opcode, 19, 16);
7688 setflags = BitIsSet(opcode, 20);
7689 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7690 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7691 // TODO: Emulate SUBS PC, LR and related instructions.
7692 if (Rd == 15 && setflags)
7693 return false;
7694 break;
7695 default:
7696 return false;
7697 }
7698 // Read the register value from the operand register Rn.
7699 uint32_t reg_val = ReadCoreReg(Rn, &success);
7700 if (!success)
7701 return false;
7702
7703 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
7704
7705 EmulateInstruction::Context context;
7706 context.type = EmulateInstruction::eContextImmediate;
7707 context.SetNoArgs ();
7708
7709 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7710 return false;
7711
7712 return true;
7713}
7714
7715// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
7716// result to the destination register. It can optionally update the condition flags based on the result.
7717bool
7718EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
7719{
7720#if 0
7721 // ARM pseudo code...
7722 if ConditionPassed() then
7723 EncodingSpecificOperations();
7724 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7725 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
7726 if d == 15 then // Can only occur for ARM encoding
7727 ALUWritePC(result); // setflags is always FALSE here
7728 else
7729 R[d] = result;
7730 if setflags then
7731 APSR.N = result<31>;
7732 APSR.Z = IsZeroBit(result);
7733 APSR.C = carry;
7734 APSR.V = overflow;
7735#endif
7736
7737 bool success = false;
7738 const uint32_t opcode = OpcodeAsUnsigned (&success);
7739 if (!success)
7740 return false;
7741
7742 uint32_t Rd; // the destination register
7743 uint32_t Rn; // the first operand
7744 uint32_t Rm; // the second operand
7745 bool setflags;
7746 ARM_ShifterType shift_t;
7747 uint32_t shift_n; // the shift applied to the value read from Rm
7748 switch (encoding) {
7749 case eEncodingT1:
7750 Rd = Bits32(opcode, 11, 8);
7751 Rn = Bits32(opcode, 19, 16);
7752 Rm = Bits32(opcode, 3, 0);
7753 setflags = BitIsSet(opcode, 20);
7754 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7755 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
7756 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
7757 return false;
7758 break;
7759 case eEncodingA1:
7760 Rd = Bits32(opcode, 15, 12);
7761 Rn = Bits32(opcode, 19, 16);
7762 Rm = Bits32(opcode, 3, 0);
7763 setflags = BitIsSet(opcode, 20);
7764 shift_n = DecodeImmShiftARM(opcode, shift_t);
7765 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7766 // TODO: Emulate SUBS PC, LR and related instructions.
7767 if (Rd == 15 && setflags)
7768 return false;
7769 break;
7770 default:
7771 return false;
7772 }
7773 // Read the register value from register Rn.
7774 uint32_t val1 = ReadCoreReg(Rn, &success);
7775 if (!success)
7776 return false;
7777
7778 // Read the register value from register Rm.
7779 uint32_t val2 = ReadCoreReg(Rm, &success);
7780 if (!success)
7781 return false;
7782
7783 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7784 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
7785
7786 EmulateInstruction::Context context;
7787 context.type = EmulateInstruction::eContextImmediate;
7788 context.SetNoArgs();
7789 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7790 return false;
7791
7792 return true;
7793}
7794
Johnny Chen90e607b2011-02-23 00:07:09 +00007795// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
7796// an immediate value, and writes the result to the destination register. It can optionally update the condition
7797// flags based on the result.
7798bool
7799EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
7800{
7801#if 0
7802 // ARM pseudo code...
7803 if ConditionPassed() then
7804 EncodingSpecificOperations();
7805 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
7806 if d == 15 then
7807 ALUWritePC(result); // setflags is always FALSE here
7808 else
7809 R[d] = result;
7810 if setflags then
7811 APSR.N = result<31>;
7812 APSR.Z = IsZeroBit(result);
7813 APSR.C = carry;
7814 APSR.V = overflow;
7815#endif
7816
7817 bool success = false;
7818 const uint32_t opcode = OpcodeAsUnsigned (&success);
7819 if (!success)
7820 return false;
7821
7822 uint32_t Rd; // the destination register
7823 uint32_t Rn; // the first operand
7824 bool setflags;
7825 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7826 switch (encoding) {
7827 case eEncodingA1:
7828 Rd = Bits32(opcode, 15, 12);
7829 Rn = Bits32(opcode, 19, 16);
7830 setflags = BitIsSet(opcode, 20);
7831 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7832 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7833 // TODO: Emulate SUBS PC, LR and related instructions.
7834 if (Rd == 15 && setflags)
7835 return false;
7836 break;
7837 default:
7838 return false;
7839 }
7840 // Read the register value from the operand register Rn.
7841 uint32_t reg_val = ReadCoreReg(Rn, &success);
7842 if (!success)
7843 return false;
7844
7845 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
7846
7847 EmulateInstruction::Context context;
7848 context.type = EmulateInstruction::eContextImmediate;
7849 context.SetNoArgs ();
7850
7851 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7852 return false;
7853
7854 return true;
7855}
7856
7857// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
7858// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
7859// condition flags based on the result.
7860bool
7861EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
7862{
7863#if 0
7864 // ARM pseudo code...
7865 if ConditionPassed() then
7866 EncodingSpecificOperations();
7867 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7868 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
7869 if d == 15 then
7870 ALUWritePC(result); // setflags is always FALSE here
7871 else
7872 R[d] = result;
7873 if setflags then
7874 APSR.N = result<31>;
7875 APSR.Z = IsZeroBit(result);
7876 APSR.C = carry;
7877 APSR.V = overflow;
7878#endif
7879
7880 bool success = false;
7881 const uint32_t opcode = OpcodeAsUnsigned (&success);
7882 if (!success)
7883 return false;
7884
7885 uint32_t Rd; // the destination register
7886 uint32_t Rn; // the first operand
7887 uint32_t Rm; // the second operand
7888 bool setflags;
7889 ARM_ShifterType shift_t;
7890 uint32_t shift_n; // the shift applied to the value read from Rm
7891 switch (encoding) {
7892 case eEncodingA1:
7893 Rd = Bits32(opcode, 15, 12);
7894 Rn = Bits32(opcode, 19, 16);
7895 Rm = Bits32(opcode, 3, 0);
7896 setflags = BitIsSet(opcode, 20);
7897 shift_n = DecodeImmShiftARM(opcode, shift_t);
7898 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7899 // TODO: Emulate SUBS PC, LR and related instructions.
7900 if (Rd == 15 && setflags)
7901 return false;
7902 break;
7903 default:
7904 return false;
7905 }
7906 // Read the register value from register Rn.
7907 uint32_t val1 = ReadCoreReg(Rn, &success);
7908 if (!success)
7909 return false;
7910
7911 // Read the register value from register Rm.
7912 uint32_t val2 = ReadCoreReg(Rm, &success);
7913 if (!success)
7914 return false;
7915
7916 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7917 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
7918
7919 EmulateInstruction::Context context;
7920 context.type = EmulateInstruction::eContextImmediate;
7921 context.SetNoArgs();
7922 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7923 return false;
7924
7925 return true;
7926}
7927
Johnny Chen9b381772011-02-23 01:01:21 +00007928// Subtract with Carry (immediate) subtracts an immediate value and the value of
7929// NOT (Carry flag) from a register value, and writes the result to the destination register.
7930// It can optionally update the condition flags based on the result.
7931bool
7932EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
7933{
7934#if 0
7935 // ARM pseudo code...
7936 if ConditionPassed() then
7937 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007938 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00007939 if d == 15 then // Can only occur for ARM encoding
7940 ALUWritePC(result); // setflags is always FALSE here
7941 else
7942 R[d] = result;
7943 if setflags then
7944 APSR.N = result<31>;
7945 APSR.Z = IsZeroBit(result);
7946 APSR.C = carry;
7947 APSR.V = overflow;
7948#endif
7949
7950 bool success = false;
7951 const uint32_t opcode = OpcodeAsUnsigned (&success);
7952 if (!success)
7953 return false;
7954
7955 uint32_t Rd; // the destination register
7956 uint32_t Rn; // the first operand
7957 bool setflags;
7958 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7959 switch (encoding) {
7960 case eEncodingT1:
7961 Rd = Bits32(opcode, 11, 8);
7962 Rn = Bits32(opcode, 19, 16);
7963 setflags = BitIsSet(opcode, 20);
7964 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7965 if (BadReg(Rd) || BadReg(Rn))
7966 return false;
7967 break;
7968 case eEncodingA1:
7969 Rd = Bits32(opcode, 15, 12);
7970 Rn = Bits32(opcode, 19, 16);
7971 setflags = BitIsSet(opcode, 20);
7972 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7973 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7974 // TODO: Emulate SUBS PC, LR and related instructions.
7975 if (Rd == 15 && setflags)
7976 return false;
7977 break;
7978 default:
7979 return false;
7980 }
7981 // Read the register value from the operand register Rn.
7982 uint32_t reg_val = ReadCoreReg(Rn, &success);
7983 if (!success)
7984 return false;
7985
7986 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
7987
7988 EmulateInstruction::Context context;
7989 context.type = EmulateInstruction::eContextImmediate;
7990 context.SetNoArgs ();
7991
7992 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7993 return false;
7994
7995 return true;
7996}
7997
7998// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
7999// NOT (Carry flag) from a register value, and writes the result to the destination register.
8000// It can optionally update the condition flags based on the result.
8001bool
8002EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8003{
8004#if 0
8005 // ARM pseudo code...
8006 if ConditionPassed() then
8007 EncodingSpecificOperations();
8008 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8009 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8010 if d == 15 then // Can only occur for ARM encoding
8011 ALUWritePC(result); // setflags is always FALSE here
8012 else
8013 R[d] = result;
8014 if setflags then
8015 APSR.N = result<31>;
8016 APSR.Z = IsZeroBit(result);
8017 APSR.C = carry;
8018 APSR.V = overflow;
8019#endif
8020
8021 bool success = false;
8022 const uint32_t opcode = OpcodeAsUnsigned (&success);
8023 if (!success)
8024 return false;
8025
8026 uint32_t Rd; // the destination register
8027 uint32_t Rn; // the first operand
8028 uint32_t Rm; // the second operand
8029 bool setflags;
8030 ARM_ShifterType shift_t;
8031 uint32_t shift_n; // the shift applied to the value read from Rm
8032 switch (encoding) {
8033 case eEncodingT1:
8034 Rd = Rn = Bits32(opcode, 2, 0);
8035 Rm = Bits32(opcode, 5, 3);
8036 setflags = !InITBlock();
8037 shift_t = SRType_LSL;
8038 shift_n = 0;
8039 break;
8040 case eEncodingT2:
8041 Rd = Bits32(opcode, 11, 8);
8042 Rn = Bits32(opcode, 19, 16);
8043 Rm = Bits32(opcode, 3, 0);
8044 setflags = BitIsSet(opcode, 20);
8045 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8046 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8047 return false;
8048 break;
8049 case eEncodingA1:
8050 Rd = Bits32(opcode, 15, 12);
8051 Rn = Bits32(opcode, 19, 16);
8052 Rm = Bits32(opcode, 3, 0);
8053 setflags = BitIsSet(opcode, 20);
8054 shift_n = DecodeImmShiftARM(opcode, shift_t);
8055 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8056 // TODO: Emulate SUBS PC, LR and related instructions.
8057 if (Rd == 15 && setflags)
8058 return false;
8059 break;
8060 default:
8061 return false;
8062 }
8063 // Read the register value from register Rn.
8064 uint32_t val1 = ReadCoreReg(Rn, &success);
8065 if (!success)
8066 return false;
8067
8068 // Read the register value from register Rm.
8069 uint32_t val2 = ReadCoreReg(Rm, &success);
8070 if (!success)
8071 return false;
8072
8073 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8074 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8075
8076 EmulateInstruction::Context context;
8077 context.type = EmulateInstruction::eContextImmediate;
8078 context.SetNoArgs();
8079 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8080 return false;
8081
8082 return true;
8083}
8084
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008085// This instruction subtracts an immediate value from a register value, and writes the result
8086// to the destination register. It can optionally update the condition flags based on the result.
8087bool
8088EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8089{
8090#if 0
8091 // ARM pseudo code...
8092 if ConditionPassed() then
8093 EncodingSpecificOperations();
8094 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8095 R[d] = result;
8096 if setflags then
8097 APSR.N = result<31>;
8098 APSR.Z = IsZeroBit(result);
8099 APSR.C = carry;
8100 APSR.V = overflow;
8101#endif
8102
8103 bool success = false;
8104 const uint32_t opcode = OpcodeAsUnsigned (&success);
8105 if (!success)
8106 return false;
8107
8108 uint32_t Rd; // the destination register
8109 uint32_t Rn; // the first operand
8110 bool setflags;
8111 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8112 switch (encoding) {
8113 case eEncodingT1:
8114 Rd = Bits32(opcode, 2, 0);
8115 Rn = Bits32(opcode, 5, 3);
8116 setflags = !InITBlock();
8117 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8118 break;
8119 case eEncodingT2:
8120 Rd = Rn = Bits32(opcode, 10, 8);
8121 setflags = !InITBlock();
8122 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8123 break;
8124 case eEncodingT3:
8125 Rd = Bits32(opcode, 11, 8);
8126 Rn = Bits32(opcode, 19, 16);
8127 setflags = BitIsSet(opcode, 20);
8128 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8129
8130 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8131 if (Rd == 15 && setflags)
8132 return EmulateCMPImm(eEncodingT2);
8133
8134 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8135 if (Rn == 13)
8136 return EmulateSUBSPImm(eEncodingT2);
8137
8138 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8139 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8140 return false;
8141 break;
8142 case eEncodingT4:
8143 Rd = Bits32(opcode, 11, 8);
8144 Rn = Bits32(opcode, 19, 16);
8145 setflags = BitIsSet(opcode, 20);
8146 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8147
8148 // if Rn == '1111' then SEE ADR;
8149 if (Rn == 15)
8150 return EmulateADR(eEncodingT2);
8151
8152 // if Rn == '1101' then SEE SUB (SP minus immediate);
8153 if (Rn == 13)
8154 return EmulateSUBSPImm(eEncodingT3);
8155
8156 if (BadReg(Rd))
8157 return false;
8158 break;
8159 default:
8160 return false;
8161 }
8162 // Read the register value from the operand register Rn.
8163 uint32_t reg_val = ReadCoreReg(Rn, &success);
8164 if (!success)
8165 return false;
8166
8167 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8168
8169 EmulateInstruction::Context context;
8170 context.type = EmulateInstruction::eContextImmediate;
8171 context.SetNoArgs ();
8172
8173 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8174 return false;
8175
8176 return true;
8177}
8178
8179// This instruction subtracts an immediate value from a register value, and writes the result
8180// to the destination register. It can optionally update the condition flags based on the result.
8181bool
8182EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8183{
8184#if 0
8185 // ARM pseudo code...
8186 if ConditionPassed() then
8187 EncodingSpecificOperations();
8188 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8189 if d == 15 then
8190 ALUWritePC(result); // setflags is always FALSE here
8191 else
8192 R[d] = result;
8193 if setflags then
8194 APSR.N = result<31>;
8195 APSR.Z = IsZeroBit(result);
8196 APSR.C = carry;
8197 APSR.V = overflow;
8198#endif
8199
8200 bool success = false;
8201 const uint32_t opcode = OpcodeAsUnsigned (&success);
8202 if (!success)
8203 return false;
8204
8205 uint32_t Rd; // the destination register
8206 uint32_t Rn; // the first operand
8207 bool setflags;
8208 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8209 switch (encoding) {
8210 case eEncodingA1:
8211 Rd = Bits32(opcode, 15, 12);
8212 Rn = Bits32(opcode, 19, 16);
8213 setflags = BitIsSet(opcode, 20);
8214 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8215
8216 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8217 if (Rn == 15 && !setflags)
8218 return EmulateADR(eEncodingA2);
8219
8220 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8221 if (Rn == 13)
8222 return EmulateSUBSPImm(eEncodingA1);
8223
8224 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8225 // TODO: Emulate SUBS PC, LR and related instructions.
8226 if (Rd == 15 && setflags)
8227 return false;
8228 break;
8229 default:
8230 return false;
8231 }
8232 // Read the register value from the operand register Rn.
8233 uint32_t reg_val = ReadCoreReg(Rn, &success);
8234 if (!success)
8235 return false;
8236
8237 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8238
8239 EmulateInstruction::Context context;
8240 context.type = EmulateInstruction::eContextImmediate;
8241 context.SetNoArgs ();
8242
8243 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8244 return false;
8245
8246 return true;
8247}
8248
Johnny Chen2115b412011-02-21 23:42:44 +00008249// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8250// immediate value. It updates the condition flags based on the result, and discards the result.
8251bool
8252EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
8253{
8254#if 0
8255 // ARM pseudo code...
8256 if ConditionPassed() then
8257 EncodingSpecificOperations();
8258 result = R[n] EOR imm32;
8259 APSR.N = result<31>;
8260 APSR.Z = IsZeroBit(result);
8261 APSR.C = carry;
8262 // APSR.V unchanged
8263#endif
8264
8265 bool success = false;
8266 const uint32_t opcode = OpcodeAsUnsigned (&success);
8267 if (!success)
8268 return false;
8269
8270 if (ConditionPassed())
8271 {
8272 uint32_t Rn;
8273 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8274 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8275 switch (encoding)
8276 {
8277 case eEncodingT1:
8278 Rn = Bits32(opcode, 19, 16);
8279 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8280 if (BadReg(Rn))
8281 return false;
8282 break;
8283 case eEncodingA1:
8284 Rn = Bits32(opcode, 19, 16);
8285 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8286 break;
8287 default:
8288 return false;
8289 }
8290
8291 // Read the first operand.
8292 uint32_t val1 = ReadCoreReg(Rn, &success);
8293 if (!success)
8294 return false;
8295
8296 uint32_t result = val1 ^ imm32;
8297
8298 EmulateInstruction::Context context;
8299 context.type = EmulateInstruction::eContextImmediate;
8300 context.SetNoArgs ();
8301
8302 if (!WriteFlags(context, result, carry))
8303 return false;
8304 }
8305 return true;
8306}
8307
8308// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8309// optionally-shifted register value. It updates the condition flags based on the result, and discards
8310// the result.
8311bool
8312EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
8313{
8314#if 0
8315 // ARM pseudo code...
8316 if ConditionPassed() then
8317 EncodingSpecificOperations();
8318 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8319 result = R[n] EOR shifted;
8320 APSR.N = result<31>;
8321 APSR.Z = IsZeroBit(result);
8322 APSR.C = carry;
8323 // APSR.V unchanged
8324#endif
8325
8326 bool success = false;
8327 const uint32_t opcode = OpcodeAsUnsigned (&success);
8328 if (!success)
8329 return false;
8330
8331 if (ConditionPassed())
8332 {
8333 uint32_t Rn, Rm;
8334 ARM_ShifterType shift_t;
8335 uint32_t shift_n; // the shift applied to the value read from Rm
8336 uint32_t carry;
8337 switch (encoding)
8338 {
8339 case eEncodingT1:
8340 Rn = Bits32(opcode, 19, 16);
8341 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008342 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008343 if (BadReg(Rn) || BadReg(Rm))
8344 return false;
8345 break;
8346 case eEncodingA1:
8347 Rn = Bits32(opcode, 19, 16);
8348 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008349 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008350 break;
8351 default:
8352 return false;
8353 }
8354
8355 // Read the first operand.
8356 uint32_t val1 = ReadCoreReg(Rn, &success);
8357 if (!success)
8358 return false;
8359
8360 // Read the second operand.
8361 uint32_t val2 = ReadCoreReg(Rm, &success);
8362 if (!success)
8363 return false;
8364
8365 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8366 uint32_t result = val1 ^ shifted;
8367
8368 EmulateInstruction::Context context;
8369 context.type = EmulateInstruction::eContextImmediate;
8370 context.SetNoArgs ();
8371
8372 if (!WriteFlags(context, result, carry))
8373 return false;
8374 }
8375 return true;
8376}
8377
Johnny Chende3cce32011-02-21 21:24:49 +00008378// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8379// It updates the condition flags based on the result, and discards the result.
8380bool
8381EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8382{
8383#if 0
8384 // ARM pseudo code...
8385 if ConditionPassed() then
8386 EncodingSpecificOperations();
8387 result = R[n] AND imm32;
8388 APSR.N = result<31>;
8389 APSR.Z = IsZeroBit(result);
8390 APSR.C = carry;
8391 // APSR.V unchanged
8392#endif
8393
8394 bool success = false;
8395 const uint32_t opcode = OpcodeAsUnsigned (&success);
8396 if (!success)
8397 return false;
8398
8399 if (ConditionPassed())
8400 {
8401 uint32_t Rn;
8402 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8403 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8404 switch (encoding)
8405 {
8406 case eEncodingT1:
8407 Rn = Bits32(opcode, 19, 16);
8408 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8409 if (BadReg(Rn))
8410 return false;
8411 break;
8412 case eEncodingA1:
8413 Rn = Bits32(opcode, 19, 16);
8414 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8415 break;
8416 default:
8417 return false;
8418 }
8419
8420 // Read the first operand.
8421 uint32_t val1 = ReadCoreReg(Rn, &success);
8422 if (!success)
8423 return false;
8424
8425 uint32_t result = val1 & imm32;
8426
8427 EmulateInstruction::Context context;
8428 context.type = EmulateInstruction::eContextImmediate;
8429 context.SetNoArgs ();
8430
8431 if (!WriteFlags(context, result, carry))
8432 return false;
8433 }
8434 return true;
8435}
8436
8437// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
8438// It updates the condition flags based on the result, and discards the result.
8439bool
8440EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
8441{
8442#if 0
8443 // ARM pseudo code...
8444 if ConditionPassed() then
8445 EncodingSpecificOperations();
8446 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8447 result = R[n] AND shifted;
8448 APSR.N = result<31>;
8449 APSR.Z = IsZeroBit(result);
8450 APSR.C = carry;
8451 // APSR.V unchanged
8452#endif
8453
8454 bool success = false;
8455 const uint32_t opcode = OpcodeAsUnsigned (&success);
8456 if (!success)
8457 return false;
8458
8459 if (ConditionPassed())
8460 {
8461 uint32_t Rn, Rm;
8462 ARM_ShifterType shift_t;
8463 uint32_t shift_n; // the shift applied to the value read from Rm
8464 uint32_t carry;
8465 switch (encoding)
8466 {
8467 case eEncodingT1:
8468 Rn = Bits32(opcode, 2, 0);
8469 Rm = Bits32(opcode, 5, 3);
8470 shift_t = SRType_LSL;
8471 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008472 break;
Johnny Chende3cce32011-02-21 21:24:49 +00008473 case eEncodingT2:
8474 Rn = Bits32(opcode, 19, 16);
8475 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008476 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008477 if (BadReg(Rn) || BadReg(Rm))
8478 return false;
8479 break;
8480 case eEncodingA1:
8481 Rn = Bits32(opcode, 19, 16);
8482 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008483 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008484 break;
8485 default:
8486 return false;
8487 }
8488
8489 // Read the first operand.
8490 uint32_t val1 = ReadCoreReg(Rn, &success);
8491 if (!success)
8492 return false;
8493
8494 // Read the second operand.
8495 uint32_t val2 = ReadCoreReg(Rm, &success);
8496 if (!success)
8497 return false;
8498
8499 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8500 uint32_t result = val1 & shifted;
8501
8502 EmulateInstruction::Context context;
8503 context.type = EmulateInstruction::eContextImmediate;
8504 context.SetNoArgs ();
8505
8506 if (!WriteFlags(context, result, carry))
8507 return false;
8508 }
8509 return true;
8510}
8511
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008512EmulateInstructionARM::ARMOpcode*
8513EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00008514{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008515 static ARMOpcode
8516 g_arm_opcodes[] =
8517 {
8518 //----------------------------------------------------------------------
8519 // Prologue instructions
8520 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00008521
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008522 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008523 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8524 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00008525
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008526 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008527 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008528 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00008529 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00008530 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
8531 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008532 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00008533
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008534 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008535 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00008536
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008537 // push one register
8538 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00008539 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00008540
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008541 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00008542 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8543 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00008544
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008545 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00008546 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008547 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00008548
Johnny Chen9f687722011-02-18 00:02:28 +00008549 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8550 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00008551 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008552 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
8553
8554 //----------------------------------------------------------------------
8555 // Supervisor Call (previously Software Interrupt)
8556 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008557 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
8558
8559 //----------------------------------------------------------------------
8560 // Branch instructions
8561 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00008562 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00008563 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
8564 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8565 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8566 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008567 // for example, "bx lr"
8568 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008569 // bxj
8570 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008571
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008572 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00008573 // Data-processing instructions
8574 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008575 // adc (immediate)
8576 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
8577 // adc (register)
8578 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008579 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008580 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008581 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008582 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00008583 // adr
8584 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8585 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008586 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008587 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008588 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008589 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008590 // bic (immediate)
8591 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
8592 // bic (register)
8593 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008594 // eor (immediate)
8595 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
8596 // eor (register)
8597 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008598 // orr (immediate)
8599 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
8600 // orr (register)
8601 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008602 // rsb (immediate)
8603 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
8604 // rsb (register)
8605 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00008606 // rsc (immediate)
8607 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
8608 // rsc (register)
8609 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008610 // sbc (immediate)
8611 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8612 // sbc (register)
8613 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008614 // sub (immediate, ARM)
8615 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008616 // sub (sp minus immediate)
8617 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00008618 // teq (immediate)
8619 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
8620 // teq (register)
8621 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008622 // tst (immediate)
8623 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
8624 // tst (register)
8625 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
8626
8627
Johnny Chen01d61572011-02-25 00:23:25 +00008628 // mov (register)
8629 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008630 // mvn (immediate)
8631 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
8632 // mvn (register)
8633 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00008634 // cmn (immediate)
8635 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
8636 // cmn (register)
8637 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008638 // cmp (immediate)
8639 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
8640 // cmp (register)
8641 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008642 // asr (immediate)
8643 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008644 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00008645 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008646 // lsl (immediate)
8647 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
8648 // lsl (register)
8649 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
8650 // lsr (immediate)
8651 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
8652 // lsr (register)
8653 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008654 // rrx is a special case encoding of ror (immediate)
8655 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
8656 // ror (immediate)
8657 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
8658 // ror (register)
8659 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00008660 // mul
8661 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00008662
8663 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008664 // Load instructions
8665 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00008666 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00008667 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00008668 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008669 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00008670 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00008671 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00008672 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00008673 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008674 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008675 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008676 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008677 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008678 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008679 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00008680 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
8681 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00008682
8683 //----------------------------------------------------------------------
8684 // Store instructions
8685 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00008686 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008687 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00008688 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00008689 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
8690 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00008691
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008692
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008693 };
8694 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
8695
8696 for (size_t i=0; i<k_num_arm_opcodes; ++i)
8697 {
8698 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
8699 return &g_arm_opcodes[i];
8700 }
8701 return NULL;
8702}
Greg Clayton64c84432011-01-21 22:02:52 +00008703
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008704
8705EmulateInstructionARM::ARMOpcode*
8706EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00008707{
Johnny Chenfdd179e2011-01-31 20:09:28 +00008708
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008709 static ARMOpcode
8710 g_thumb_opcodes[] =
8711 {
8712 //----------------------------------------------------------------------
8713 // Prologue instructions
8714 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00008715
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008716 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008717 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8718 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
8719 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00008720
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008721 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008722 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008723 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00008724 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008725 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00008726 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00008727
Johnny Chen864a8e82011-02-18 00:07:39 +00008728 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00008729 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00008730
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008731 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008732 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008733 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00008734 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
8735 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008736
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008737 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00008738 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8739 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008740
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008741 //----------------------------------------------------------------------
8742 // Epilogue instructions
8743 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00008744
Johnny Chen864a8e82011-02-18 00:07:39 +00008745 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00008746 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8747 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
8748 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00008749 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
8750 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008751
8752 //----------------------------------------------------------------------
8753 // Supervisor Call (previously Software Interrupt)
8754 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00008755 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
8756
8757 //----------------------------------------------------------------------
8758 // If Then makes up to four following instructions conditional.
8759 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008760 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
8761
8762 //----------------------------------------------------------------------
8763 // Branch instructions
8764 //----------------------------------------------------------------------
8765 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
8766 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008767 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00008768 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008769 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00008770 // J1 == J2 == 1
8771 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8772 // J1 == J2 == 1
8773 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8774 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008775 // for example, "bx lr"
8776 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008777 // bxj
8778 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00008779 // compare and branch
8780 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00008781 // table branch byte
8782 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
8783 // table branch halfword
8784 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008785
8786 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00008787 // Data-processing instructions
8788 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008789 // adc (immediate)
8790 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
8791 // adc (register)
8792 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
8793 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
8794 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00008795 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00008796 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00008797 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00008798 // adr
8799 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8800 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
8801 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008802 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008803 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008804 // and (register)
8805 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
8806 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008807 // bic (immediate)
8808 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
8809 // bic (register)
8810 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
8811 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008812 // eor (immediate)
8813 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
8814 // eor (register)
8815 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
8816 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008817 // orr (immediate)
8818 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
8819 // orr (register)
8820 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
8821 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008822 // rsb (immediate)
8823 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
8824 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
8825 // rsb (register)
8826 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008827 // sbc (immediate)
8828 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8829 // sbc (register)
8830 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
8831 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008832 // sub (immediate, Thumb)
8833 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
8834 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
8835 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
8836 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008837 // sub (sp minus immediate)
8838 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
8839 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00008840 // teq (immediate)
8841 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
8842 // teq (register)
8843 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008844 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00008845 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00008846 // tst (register)
8847 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
8848 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
8849
Johnny Chen7c5234d2011-02-18 23:41:11 +00008850
Johnny Chen338bf542011-02-10 19:29:03 +00008851 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00008852 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00008853 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00008854 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008855 // mov{s}<c>.w <Rd>, <Rm>
8856 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00008857 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00008858 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
8859 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008860 // mvn (immediate)
8861 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
8862 // mvn (register)
8863 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
8864 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008865 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00008866 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008867 // cmn (register)
8868 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008869 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008870 // cmp (immediate)
8871 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008872 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008873 // cmp (register) (Rn and Rm both from r0-r7)
8874 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
8875 // cmp (register) (Rn and Rm not both from r0-r7)
8876 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008877 // asr (immediate)
8878 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00008879 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00008880 // asr (register)
8881 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
8882 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008883 // lsl (immediate)
8884 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
8885 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
8886 // lsl (register)
8887 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
8888 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
8889 // lsr (immediate)
8890 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
8891 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
8892 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00008893 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008894 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008895 // rrx is a special case encoding of ror (immediate)
8896 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
8897 // ror (immediate)
8898 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
8899 // ror (register)
8900 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
8901 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00008902 // mul
8903 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
8904 // mul
8905 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Johnny Chen26863dc2011-02-09 23:43:29 +00008906
8907 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008908 // Load instructions
8909 //----------------------------------------------------------------------
8910 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00008911 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00008912 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00008913 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
8914 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00008915 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00008916 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
8917 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00008918 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
8919 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
8920 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00008921 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00008922 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
8923 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00008924 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
8925 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
8926 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008927 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008928 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
8929 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008930 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
8931 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008932 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008933 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
8934 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008935 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
8936 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00008937 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00008938 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
8939 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00008940
8941 //----------------------------------------------------------------------
8942 // Store instructions
8943 //----------------------------------------------------------------------
8944 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008945 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00008946 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00008947 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
8948 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
8949 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
8950 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
8951 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
8952 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
8953 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
8954 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
8955 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008956 };
8957
8958 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
8959 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
8960 {
8961 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
8962 return &g_thumb_opcodes[i];
8963 }
8964 return NULL;
8965}
Greg Clayton64c84432011-01-21 22:02:52 +00008966
Greg Clayton31e2a382011-01-30 20:03:56 +00008967bool
Greg Clayton395fc332011-02-15 21:59:32 +00008968EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00008969{
8970 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00008971 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00008972 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00008973 {
Greg Clayton395fc332011-02-15 21:59:32 +00008974 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
8975 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
8976 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
8977 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
8978 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
8979 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
8980 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
8981 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
8982 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
8983 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00008984 }
8985 return m_arm_isa != 0;
8986}
8987
8988
Greg Clayton64c84432011-01-21 22:02:52 +00008989bool
8990EmulateInstructionARM::ReadInstruction ()
8991{
8992 bool success = false;
8993 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
8994 if (success)
8995 {
8996 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
8997 if (success)
8998 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00008999 Context read_inst_context;
9000 read_inst_context.type = eContextReadOpcode;
9001 read_inst_context.SetNoArgs ();
9002
Greg Clayton64c84432011-01-21 22:02:52 +00009003 if (m_inst_cpsr & MASK_CPSR_T)
9004 {
9005 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009006 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009007
9008 if (success)
9009 {
9010 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9011 {
9012 m_inst.opcode_type = eOpcode16;
9013 m_inst.opcode.inst16 = thumb_opcode;
9014 }
9015 else
9016 {
9017 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009018 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009019 }
9020 }
9021 }
9022 else
9023 {
9024 m_inst_mode = eModeARM;
9025 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009026 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009027 }
9028 }
9029 }
9030 if (!success)
9031 {
9032 m_inst_mode = eModeInvalid;
9033 m_inst_pc = LLDB_INVALID_ADDRESS;
9034 }
9035 return success;
9036}
9037
Johnny Chenee9b1f72011-02-09 01:00:31 +00009038uint32_t
9039EmulateInstructionARM::ArchVersion ()
9040{
9041 return m_arm_isa;
9042}
9043
Greg Clayton64c84432011-01-21 22:02:52 +00009044bool
9045EmulateInstructionARM::ConditionPassed ()
9046{
9047 if (m_inst_cpsr == 0)
9048 return false;
9049
9050 const uint32_t cond = CurrentCond ();
9051
9052 if (cond == UINT32_MAX)
9053 return false;
9054
9055 bool result = false;
9056 switch (UnsignedBits(cond, 3, 1))
9057 {
9058 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9059 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9060 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9061 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9062 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9063 case 5:
9064 {
9065 bool n = (m_inst_cpsr & MASK_CPSR_N);
9066 bool v = (m_inst_cpsr & MASK_CPSR_V);
9067 result = n == v;
9068 }
9069 break;
9070 case 6:
9071 {
9072 bool n = (m_inst_cpsr & MASK_CPSR_N);
9073 bool v = (m_inst_cpsr & MASK_CPSR_V);
9074 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9075 }
9076 break;
9077 case 7:
9078 result = true;
9079 break;
9080 }
9081
9082 if (cond & 1)
9083 result = !result;
9084 return result;
9085}
9086
Johnny Chen9ee056b2011-02-08 00:06:35 +00009087uint32_t
9088EmulateInstructionARM::CurrentCond ()
9089{
9090 switch (m_inst_mode)
9091 {
9092 default:
9093 case eModeInvalid:
9094 break;
9095
9096 case eModeARM:
9097 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9098
9099 case eModeThumb:
9100 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9101 // 'cond' field of the encoding.
9102 if (m_inst.opcode_type == eOpcode16 &&
9103 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9104 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9105 {
9106 return Bits32(m_inst.opcode.inst16, 11, 7);
9107 }
9108 else if (m_inst.opcode_type == eOpcode32 &&
9109 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9110 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9111 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9112 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9113 {
9114 return Bits32(m_inst.opcode.inst32, 25, 22);
9115 }
9116
9117 return m_it_session.GetCond();
9118 }
9119 return UINT32_MAX; // Return invalid value
9120}
9121
Johnny Chen9ee056b2011-02-08 00:06:35 +00009122bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009123EmulateInstructionARM::InITBlock()
9124{
9125 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9126}
9127
9128bool
9129EmulateInstructionARM::LastInITBlock()
9130{
9131 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9132}
9133
9134bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009135EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9136{
9137 addr_t target;
9138
Johnny Chenee9b1f72011-02-09 01:00:31 +00009139 // Check the current instruction set.
9140 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009141 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009142 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009143 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009144
Johnny Chen9ee056b2011-02-08 00:06:35 +00009145 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009146 return false;
9147
9148 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009149}
9150
9151// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9152bool
Johnny Chen668b4512011-02-15 21:08:58 +00009153EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009154{
9155 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009156 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9157 // we want to record it and issue a WriteRegister callback so the clients
9158 // can track the mode changes accordingly.
9159 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009160
9161 if (BitIsSet(addr, 0))
9162 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009163 if (CurrentInstrSet() != eModeThumb)
9164 {
9165 SelectInstrSet(eModeThumb);
9166 cpsr_changed = true;
9167 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009168 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009169 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009170 }
9171 else if (BitIsClear(addr, 1))
9172 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009173 if (CurrentInstrSet() != eModeARM)
9174 {
9175 SelectInstrSet(eModeARM);
9176 cpsr_changed = true;
9177 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009178 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009179 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009180 }
9181 else
9182 return false; // address<1:0> == '10' => UNPREDICTABLE
9183
Johnny Chen0f309db2011-02-09 19:11:32 +00009184 if (cpsr_changed)
9185 {
Johnny Chen558133b2011-02-09 23:59:17 +00009186 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009187 return false;
9188 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009189 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009190 return false;
9191
9192 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009193}
Greg Clayton64c84432011-01-21 22:02:52 +00009194
Johnny Chenee9b1f72011-02-09 01:00:31 +00009195// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9196bool
Johnny Chen668b4512011-02-15 21:08:58 +00009197EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009198{
9199 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009200 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009201 else
9202 return BranchWritePC((const Context)context, addr);
9203}
9204
Johnny Chen26863dc2011-02-09 23:43:29 +00009205// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9206bool
Johnny Chen668b4512011-02-15 21:08:58 +00009207EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009208{
9209 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009210 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009211 else
9212 return BranchWritePC((const Context)context, addr);
9213}
9214
Johnny Chenee9b1f72011-02-09 01:00:31 +00009215EmulateInstructionARM::Mode
9216EmulateInstructionARM::CurrentInstrSet ()
9217{
9218 return m_inst_mode;
9219}
9220
9221// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009222// ReadInstruction() is performed. This function has a side effect of updating
9223// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009224bool
9225EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9226{
Johnny Chen558133b2011-02-09 23:59:17 +00009227 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009228 switch (arm_or_thumb)
9229 {
9230 default:
9231 return false;
9232 eModeARM:
9233 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009234 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009235 break;
9236 eModeThumb:
9237 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009238 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009239 break;
9240 }
9241 return true;
9242}
9243
Johnny Chenef21b592011-02-10 01:52:38 +00009244// This function returns TRUE if the processor currently provides support for
9245// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9246// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9247bool
9248EmulateInstructionARM::UnalignedSupport()
9249{
9250 return (ArchVersion() >= ARMv7);
9251}
9252
Johnny Chenbf6ad172011-02-11 01:29:53 +00009253// The main addition and subtraction instructions can produce status information
9254// about both unsigned carry and signed overflow conditions. This status
9255// information can be used to synthesize multi-word additions and subtractions.
9256EmulateInstructionARM::AddWithCarryResult
9257EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9258{
9259 uint32_t result;
9260 uint8_t carry_out;
9261 uint8_t overflow;
9262
9263 uint64_t unsigned_sum = x + y + carry_in;
9264 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9265
9266 result = UnsignedBits(unsigned_sum, 31, 0);
9267 carry_out = (result == unsigned_sum ? 0 : 1);
9268 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9269
9270 AddWithCarryResult res = { result, carry_out, overflow };
9271 return res;
9272}
9273
Johnny Chen157b9592011-02-18 21:13:05 +00009274uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00009275EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00009276{
Johnny Chene39f22d2011-02-19 01:36:13 +00009277 uint32_t reg_kind, reg_num;
9278 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00009279 {
Johnny Chene39f22d2011-02-19 01:36:13 +00009280 case SP_REG:
9281 reg_kind = eRegisterKindGeneric;
9282 reg_num = LLDB_REGNUM_GENERIC_SP;
9283 break;
9284 case LR_REG:
9285 reg_kind = eRegisterKindGeneric;
9286 reg_num = LLDB_REGNUM_GENERIC_RA;
9287 break;
9288 case PC_REG:
9289 reg_kind = eRegisterKindGeneric;
9290 reg_num = LLDB_REGNUM_GENERIC_PC;
9291 break;
9292 default:
9293 if (0 <= num && num < SP_REG)
9294 {
9295 reg_kind = eRegisterKindDWARF;
9296 reg_num = dwarf_r0 + num;
9297 }
Johnny Chen157b9592011-02-18 21:13:05 +00009298 else
Johnny Chene39f22d2011-02-19 01:36:13 +00009299 {
9300 assert(0 && "Invalid register number");
9301 *success = false;
9302 return ~0u;
9303 }
9304 break;
Johnny Chen157b9592011-02-18 21:13:05 +00009305 }
Johnny Chene39f22d2011-02-19 01:36:13 +00009306
9307 // Read our register.
9308 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
9309
9310 // When executing an ARM instruction , PC reads as the address of the current
9311 // instruction plus 8.
9312 // When executing a Thumb instruction , PC reads as the address of the current
9313 // instruction plus 4.
9314 if (num == 15)
9315 {
9316 if (CurrentInstrSet() == eModeARM)
9317 val += 8;
9318 else
9319 val += 4;
9320 }
Johnny Chen157b9592011-02-18 21:13:05 +00009321
9322 return val;
9323}
9324
Johnny Chenca67d1c2011-02-17 01:35:27 +00009325// Write the result to the ARM core register Rd, and optionally update the
9326// condition flags based on the result.
9327//
9328// This helper method tries to encapsulate the following pseudocode from the
9329// ARM Architecture Reference Manual:
9330//
9331// if d == 15 then // Can only occur for encoding A1
9332// ALUWritePC(result); // setflags is always FALSE here
9333// else
9334// R[d] = result;
9335// if setflags then
9336// APSR.N = result<31>;
9337// APSR.Z = IsZeroBit(result);
9338// APSR.C = carry;
9339// // APSR.V unchanged
9340//
9341// In the above case, the API client does not pass in the overflow arg, which
9342// defaults to ~0u.
9343bool
Johnny Chen10530c22011-02-17 22:37:12 +00009344EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
9345 const uint32_t result,
9346 const uint32_t Rd,
9347 bool setflags,
9348 const uint32_t carry,
9349 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00009350{
9351 if (Rd == 15)
9352 {
9353 if (!ALUWritePC (context, result))
9354 return false;
9355 }
9356 else
9357 {
Johnny Chena695f952011-02-23 21:24:25 +00009358 uint32_t reg_kind, reg_num;
9359 switch (Rd)
9360 {
9361 case SP_REG:
9362 reg_kind = eRegisterKindGeneric;
9363 reg_num = LLDB_REGNUM_GENERIC_SP;
9364 break;
9365 case LR_REG:
9366 reg_kind = eRegisterKindGeneric;
9367 reg_num = LLDB_REGNUM_GENERIC_RA;
9368 break;
9369 default:
9370 reg_kind = eRegisterKindDWARF;
9371 reg_num = dwarf_r0 + Rd;
9372 }
9373 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00009374 return false;
9375 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00009376 return WriteFlags (context, result, carry, overflow);
9377 }
9378 return true;
9379}
9380
9381// This helper method tries to encapsulate the following pseudocode from the
9382// ARM Architecture Reference Manual:
9383//
9384// APSR.N = result<31>;
9385// APSR.Z = IsZeroBit(result);
9386// APSR.C = carry;
9387// APSR.V = overflow
9388//
9389// Default arguments can be specified for carry and overflow parameters, which means
9390// not to update the respective flags.
9391bool
9392EmulateInstructionARM::WriteFlags (Context &context,
9393 const uint32_t result,
9394 const uint32_t carry,
9395 const uint32_t overflow)
9396{
9397 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00009398 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
9399 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00009400 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009401 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00009402 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009403 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00009404 if (m_new_inst_cpsr != m_inst_cpsr)
9405 {
9406 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
9407 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00009408 }
9409 return true;
9410}
9411
Greg Clayton64c84432011-01-21 22:02:52 +00009412bool
9413EmulateInstructionARM::EvaluateInstruction ()
9414{
Johnny Chenc315f862011-02-05 00:46:10 +00009415 // Advance the ITSTATE bits to their values for the next instruction.
9416 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
9417 m_it_session.ITAdvance();
9418
Greg Clayton64c84432011-01-21 22:02:52 +00009419 return false;
9420}