blob: 25ea47c05593f7ae5c5eef23d2369cca43910643 [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.
27#define APSR_C Bit32(m_inst_cpsr, CPSR_C)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V)
29
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
113#define PC_REG 15
114#define PC_REGLIST_BIT 0x8000
115
Johnny Chen251af6a2011-01-21 22:47:25 +0000116#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000117#define ARMv4T (1u << 1)
118#define ARMv5T (1u << 2)
119#define ARMv5TE (1u << 3)
120#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000121#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000122#define ARMv6K (1u << 6)
123#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000124#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000125#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000126#define ARMvAll (0xffffffffu)
127
Johnny Chen9b8d7832011-02-02 01:13:56 +0000128#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
129#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
130#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000131
Johnny Chen0e00af22011-02-10 19:40:42 +0000132//----------------------------------------------------------------------
133//
134// EmulateInstructionARM implementation
135//
136//----------------------------------------------------------------------
137
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000138void
139EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000140{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000142
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143void
144EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000145{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000146}
147
Caroline Ticefa172202011-02-11 22:49:54 +0000148// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
149bool
150EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
151{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000152 EmulateInstruction::Context context;
153 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
154 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000155
156 uint32_t random_data = rand ();
157 const uint32_t addr_byte_size = GetAddressByteSize();
158
Caroline Ticecc96eb52011-02-17 19:20:40 +0000159 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000160 return false;
161
162 return true;
163}
164
Caroline Tice713c2662011-02-11 17:59:55 +0000165// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
166bool
167EmulateInstructionARM::WriteBits32Unknown (int n)
168{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000169 EmulateInstruction::Context context;
170 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
171 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000172
Johnny Chen62ff6f52011-02-11 18:11:22 +0000173 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000174 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
175
176 if (!success)
177 return false;
178
179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
180 return false;
181
182 return true;
183}
184
Johnny Chen08c25e82011-01-31 18:02:28 +0000185// Push Multiple Registers stores multiple registers to the stack, storing to
186// consecutive memory locations ending just below the address in SP, and updates
187// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000188bool
Johnny Chen9f687722011-02-18 00:02:28 +0000189EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000190{
191#if 0
192 // ARM pseudo code...
193 if (ConditionPassed())
194 {
195 EncodingSpecificOperations();
196 NullCheckIfThumbEE(13);
197 address = SP - 4*BitCount(registers);
198
199 for (i = 0 to 14)
200 {
201 if (registers<i> == ’1’)
202 {
203 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
204 MemA[address,4] = bits(32) UNKNOWN;
205 else
206 MemA[address,4] = R[i];
207 address = address + 4;
208 }
209 }
210
211 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
212 MemA[address,4] = PCStoreValue();
213
214 SP = SP - 4*BitCount(registers);
215 }
216#endif
217
218 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000219 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000220 if (!success)
221 return false;
222
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000224 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000225 const uint32_t addr_byte_size = GetAddressByteSize();
226 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000227 if (!success)
228 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000229 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000230 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000231 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000232 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000233 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000234 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000235 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000236 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // if BitCount(registers) < 1 then UNPREDICTABLE;
238 if (BitCount(registers) < 1)
239 return false;
240 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000241 case eEncodingT2:
242 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000243 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 // if BitCount(registers) < 2 then UNPREDICTABLE;
245 if (BitCount(registers) < 2)
246 return false;
247 break;
248 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000249 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000250 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000251 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000252 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000253 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000255 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000256 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000257 // Instead of return false, let's handle the following case as well,
258 // which amounts to pushing one reg onto the full descending stacks.
259 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000260 break;
261 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000262 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000263 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000264 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000265 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000266 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000267 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000268 default:
269 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 }
Johnny Chence1ca772011-01-25 01:13:00 +0000271 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000272 addr_t addr = sp - sp_offset;
273 uint32_t i;
274
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000275 EmulateInstruction::Context context;
276 context.type = EmulateInstruction::eContextPushRegisterOnStack;
277 Register dwarf_reg;
278 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000279 for (i=0; i<15; ++i)
280 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000281 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000282 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000283 dwarf_reg.num = dwarf_r0 + i;
284 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
285 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000286 if (!success)
287 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000288 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000289 return false;
290 addr += addr_byte_size;
291 }
292 }
293
Johnny Chen7c1bf922011-02-08 23:49:37 +0000294 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000296 dwarf_reg.num = dwarf_pc;
297 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000298 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000299 if (!success)
300 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000301 if (!MemAWrite (context, addr, pc + 8, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000302 return false;
303 }
304
305 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000306 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000307
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000308 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000309 return false;
310 }
311 return true;
312}
313
Johnny Chenef85e912011-01-31 23:07:40 +0000314// Pop Multiple Registers loads multiple registers from the stack, loading from
315// consecutive memory locations staring at the address in SP, and updates
316// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000317bool
Johnny Chen9f687722011-02-18 00:02:28 +0000318EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000319{
320#if 0
321 // ARM pseudo code...
322 if (ConditionPassed())
323 {
324 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
325 address = SP;
326 for i = 0 to 14
327 if registers<i> == ‘1’ then
328 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
329 if registers<15> == ‘1’ then
330 if UnalignedAllowed then
331 LoadWritePC(MemU[address,4]);
332 else
333 LoadWritePC(MemA[address,4]);
334 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
335 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
336 }
337#endif
338
339 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000340 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000341 if (!success)
342 return false;
343
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000345 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t addr_byte_size = GetAddressByteSize();
347 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000348 if (!success)
349 return false;
350 uint32_t registers = 0;
351 uint32_t Rt; // the destination register
352 switch (encoding) {
353 case eEncodingT1:
354 registers = Bits32(opcode, 7, 0);
355 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000356 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000357 registers |= (1u << 15);
358 // if BitCount(registers) < 1 then UNPREDICTABLE;
359 if (BitCount(registers) < 1)
360 return false;
361 break;
362 case eEncodingT2:
363 // Ignore bit 13.
364 registers = Bits32(opcode, 15, 0) & ~0x2000;
365 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000366 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000367 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000368 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
369 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
370 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000371 break;
372 case eEncodingT3:
373 Rt = Bits32(opcode, 15, 12);
374 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000375 if (Rt == 13)
376 return false;
377 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000378 return false;
379 registers = (1u << Rt);
380 break;
381 case eEncodingA1:
382 registers = Bits32(opcode, 15, 0);
383 // Instead of return false, let's handle the following case as well,
384 // which amounts to popping one reg from the full descending stacks.
385 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
386
387 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000388 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000389 return false;
390 break;
391 case eEncodingA2:
392 Rt = Bits32(opcode, 15, 12);
393 // if t == 13 then UNPREDICTABLE;
394 if (Rt == dwarf_sp)
395 return false;
396 registers = (1u << Rt);
397 break;
398 default:
399 return false;
400 }
401 addr_t sp_offset = addr_byte_size * BitCount (registers);
402 addr_t addr = sp;
403 uint32_t i, data;
404
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000405 EmulateInstruction::Context context;
406 context.type = EmulateInstruction::eContextPopRegisterOffStack;
407 Register dwarf_reg;
408 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000409 for (i=0; i<15; ++i)
410 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000411 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000412 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000413 dwarf_reg.num = dwarf_r0 + i;
414 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000415 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000416 if (!success)
417 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000418 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000419 return false;
420 addr += addr_byte_size;
421 }
422 }
423
Johnny Chen7c1bf922011-02-08 23:49:37 +0000424 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000425 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000426 dwarf_reg.num = dwarf_pc;
427 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000428 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000429 if (!success)
430 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000431 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000432 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000433 return false;
434 addr += addr_byte_size;
435 }
436
437 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000438 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000439
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000440 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000441 return false;
442 }
443 return true;
444}
445
Johnny Chen5b442b72011-01-27 19:34:30 +0000446// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000447// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448bool
Johnny Chen9f687722011-02-18 00:02:28 +0000449EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000450{
451#if 0
452 // ARM pseudo code...
453 if (ConditionPassed())
454 {
455 EncodingSpecificOperations();
456 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
457 if d == 15 then
458 ALUWritePC(result); // setflags is always FALSE here
459 else
460 R[d] = result;
461 if setflags then
462 APSR.N = result<31>;
463 APSR.Z = IsZeroBit(result);
464 APSR.C = carry;
465 APSR.V = overflow;
466 }
467#endif
468
469 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000470 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000471 if (!success)
472 return false;
473
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 if (!success)
478 return false;
479 uint32_t Rd; // the destination register
480 uint32_t imm32;
481 switch (encoding) {
482 case eEncodingT1:
483 Rd = 7;
484 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
485 break;
486 case eEncodingA1:
487 Rd = Bits32(opcode, 15, 12);
488 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
489 break;
490 default:
491 return false;
492 }
493 addr_t sp_offset = imm32;
494 addr_t addr = sp + sp_offset; // a pointer to the stack area
495
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000496 EmulateInstruction::Context context;
497 context.type = EmulateInstruction::eContextRegisterPlusOffset;
498 Register sp_reg;
499 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
500 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000501
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000502 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000503 return false;
504 }
505 return true;
506}
507
Johnny Chen2ccad832011-01-28 19:57:25 +0000508// Set r7 or ip to the current stack pointer.
509// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510bool
Johnny Chen9f687722011-02-18 00:02:28 +0000511EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000512{
513#if 0
514 // ARM pseudo code...
515 if (ConditionPassed())
516 {
517 EncodingSpecificOperations();
518 result = R[m];
519 if d == 15 then
520 ALUWritePC(result); // setflags is always FALSE here
521 else
522 R[d] = result;
523 if setflags then
524 APSR.N = result<31>;
525 APSR.Z = IsZeroBit(result);
526 // APSR.C unchanged
527 // APSR.V unchanged
528 }
529#endif
530
531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000532 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000533 //if (!success)
534 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000535
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000537 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000539 if (!success)
540 return false;
541 uint32_t Rd; // the destination register
542 switch (encoding) {
543 case eEncodingT1:
544 Rd = 7;
545 break;
546 case eEncodingA1:
547 Rd = 12;
548 break;
549 default:
550 return false;
551 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000552
553 EmulateInstruction::Context context;
554 context.type = EmulateInstruction::eContextRegisterPlusOffset;
555 Register sp_reg;
556 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
557 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000558
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000559 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000560 return false;
561 }
562 return true;
563}
564
Johnny Chen1c13b622011-01-29 00:11:15 +0000565// Move from high register (r8-r15) to low register (r0-r7).
566// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567bool
Johnny Chen9f687722011-02-18 00:02:28 +0000568EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000569{
Johnny Chen9f687722011-02-18 00:02:28 +0000570 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000571}
572
573// Move from register to register.
574// MOV (register)
575bool
Johnny Chen9f687722011-02-18 00:02:28 +0000576EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000577{
Johnny Chen1c13b622011-01-29 00:11:15 +0000578#if 0
579 // ARM pseudo code...
580 if (ConditionPassed())
581 {
582 EncodingSpecificOperations();
583 result = R[m];
584 if d == 15 then
585 ALUWritePC(result); // setflags is always FALSE here
586 else
587 R[d] = result;
588 if setflags then
589 APSR.N = result<31>;
590 APSR.Z = IsZeroBit(result);
591 // APSR.C unchanged
592 // APSR.V unchanged
593 }
594#endif
595
596 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000597 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000598 if (!success)
599 return false;
600
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000601 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000602 {
603 uint32_t Rm; // the source register
604 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000605 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 switch (encoding) {
607 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000608 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000609 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000610 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000611 if (Rd == 15 && InITBlock() && !LastInITBlock())
612 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000613 break;
614 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000615 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000616 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000617 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000618 if (InITBlock())
619 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000620 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000621 case eEncodingT3:
622 Rd = Bits32(opcode, 11, 8);
623 Rm = Bits32(opcode, 3, 0);
624 setflags = BitIsSet(opcode, 20);
625 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
626 if (setflags && (BadReg(Rd) || BadReg(Rm)))
627 return false;
628 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
629 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
630 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000631 default:
632 return false;
633 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000634 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000635 if (!success)
636 return false;
637
638 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000639 EmulateInstruction::Context context;
640 context.type = EmulateInstruction::eContextRegisterPlusOffset;
641 Register dwarf_reg;
642 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
643 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000644
Johnny Chen10530c22011-02-17 22:37:12 +0000645 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000646 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000647 }
648 return true;
649}
650
Johnny Chen357c30f2011-02-14 22:04:25 +0000651// Move (immediate) writes an immediate value to the destination register. It
652// can optionally update the condition flags based on the value.
653// MOV (immediate)
654bool
Johnny Chen9f687722011-02-18 00:02:28 +0000655EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000656{
657#if 0
658 // ARM pseudo code...
659 if (ConditionPassed())
660 {
661 EncodingSpecificOperations();
662 result = imm32;
663 if d == 15 then // Can only occur for ARM encoding
664 ALUWritePC(result); // setflags is always FALSE here
665 else
666 R[d] = result;
667 if setflags then
668 APSR.N = result<31>;
669 APSR.Z = IsZeroBit(result);
670 APSR.C = carry;
671 // APSR.V unchanged
672 }
673#endif
674 bool success = false;
675 const uint32_t opcode = OpcodeAsUnsigned (&success);
676 if (!success)
677 return false;
678
679 if (ConditionPassed())
680 {
681 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000682 uint32_t imm32; // the immediate value to be written to Rd
683 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
684 bool setflags;
685 switch (encoding) {
686 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000687 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000688 setflags = !InITBlock();
689 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000690 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000691 break;
692 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000693 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000694 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000695 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000696 if (BadReg(Rd))
697 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000698 break;
699 default:
700 return false;
701 }
702 uint32_t result = imm32;
703
704 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000705 EmulateInstruction::Context context;
706 context.type = EmulateInstruction::eContextImmediate;
707 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000708
Johnny Chen10530c22011-02-17 22:37:12 +0000709 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000710 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000711 }
712 return true;
713}
714
Johnny Chen28070c32011-02-12 01:27:26 +0000715// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
716// the destination register. It can optionally update the condition flags based
717// on the value.
718// MVN (immediate)
719bool
Johnny Chen9f687722011-02-18 00:02:28 +0000720EmulateInstructionARM::EmulateMVNRdImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000721{
722#if 0
723 // ARM pseudo code...
724 if (ConditionPassed())
725 {
726 EncodingSpecificOperations();
727 result = NOT(imm32);
728 if d == 15 then // Can only occur for ARM encoding
729 ALUWritePC(result); // setflags is always FALSE here
730 else
731 R[d] = result;
732 if setflags then
733 APSR.N = result<31>;
734 APSR.Z = IsZeroBit(result);
735 APSR.C = carry;
736 // APSR.V unchanged
737 }
738#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000739 bool success = false;
740 const uint32_t opcode = OpcodeAsUnsigned (&success);
741 if (!success)
742 return false;
743
744 if (ConditionPassed())
745 {
746 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000747 uint32_t imm12; // the first operand to ThumbExpandImm_C or ARMExpandImm_C
748 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
749 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000750 bool setflags;
751 switch (encoding) {
752 case eEncodingT1:
753 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000754 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000755 imm12 = Bit32(opcode, 26) << 11 | Bits32(opcode, 14, 12) << 8 | Bits32(opcode, 7, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000756 imm32 = ThumbExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000757 break;
758 case eEncodingA1:
759 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000760 setflags = BitIsSet(opcode, 20);
Johnny Chen357c30f2011-02-14 22:04:25 +0000761 imm12 = Bits32(opcode, 11, 0);
Johnny Chene97c0d52011-02-18 19:32:20 +0000762 imm32 = ARMExpandImm_C(imm12, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000763 break;
764 default:
765 return false;
766 }
767 uint32_t result = ~imm32;
768
769 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000770 EmulateInstruction::Context context;
771 context.type = EmulateInstruction::eContextImmediate;
772 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000773
Johnny Chen10530c22011-02-17 22:37:12 +0000774 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000775 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000776 }
777 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000778}
779
Johnny Chen788e0552011-01-27 22:52:23 +0000780// PC relative immediate load into register, possibly followed by ADD (SP plus register).
781// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000782bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000783EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000784{
785#if 0
786 // ARM pseudo code...
787 if (ConditionPassed())
788 {
789 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
790 base = Align(PC,4);
791 address = if add then (base + imm32) else (base - imm32);
792 data = MemU[address,4];
793 if t == 15 then
794 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
795 elsif UnalignedSupport() || address<1:0> = ‘00’ then
796 R[t] = data;
797 else // Can only apply before ARMv7
798 if CurrentInstrSet() == InstrSet_ARM then
799 R[t] = ROR(data, 8*UInt(address<1:0>));
800 else
801 R[t] = bits(32) UNKNOWN;
802 }
803#endif
804
805 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000806 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000807 if (!success)
808 return false;
809
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000810 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000811 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000812 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000813 if (!success)
814 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000815
816 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000817 EmulateInstruction::Context context;
818 context.type = EmulateInstruction::eContextRegisterPlusOffset;
819 Register pc_reg;
820 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
821 context.SetRegisterPlusOffset (pc_reg, 0);
822
Johnny Chenc9de9102011-02-11 19:12:30 +0000823 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000824 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000825 bool add; // +imm32 or -imm32?
826 addr_t base; // the base address
827 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000828 uint32_t data; // the literal data value from the PC relative load
829 switch (encoding) {
830 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000831 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000832 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000833 add = true;
834 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000835 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000836 break;
837 case eEncodingT2:
838 Rt = Bits32(opcode, 15, 12);
839 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
840 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000841 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000842 return false;
843 base = Align(pc + 4, 4);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000844 context.SetRegisterPlusOffset (pc_reg, 4 + imm32);
Johnny Chen788e0552011-01-27 22:52:23 +0000845 break;
846 default:
847 return false;
848 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000849
850 if (add)
851 address = base + imm32;
852 else
853 address = base - imm32;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000854 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000855 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000856 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000857
858 if (Rt == 15)
859 {
860 if (Bits32(address, 1, 0) == 0)
861 {
862 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000863 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000864 return false;
865 }
866 else
867 return false;
868 }
869 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
870 {
871 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
872 return false;
873 }
874 else // We don't handle ARM for now.
875 return false;
876
877 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000878 return false;
879 }
880 return true;
881}
882
Johnny Chen5b442b72011-01-27 19:34:30 +0000883// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000884// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000885bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000886EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000887{
888#if 0
889 // ARM pseudo code...
890 if (ConditionPassed())
891 {
892 EncodingSpecificOperations();
893 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
894 if d == 15 then // Can only occur for ARM encoding
895 ALUWritePC(result); // setflags is always FALSE here
896 else
897 R[d] = result;
898 if setflags then
899 APSR.N = result<31>;
900 APSR.Z = IsZeroBit(result);
901 APSR.C = carry;
902 APSR.V = overflow;
903 }
904#endif
905
906 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000907 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000908 if (!success)
909 return false;
910
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000911 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +0000912 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000913 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000914 if (!success)
915 return false;
916 uint32_t imm32; // the immediate operand
917 switch (encoding) {
918 case eEncodingT2:
919 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
920 break;
921 default:
922 return false;
923 }
924 addr_t sp_offset = imm32;
925 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
926
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000927 EmulateInstruction::Context context;
928 context.type = EmulateInstruction::eContextAdjustStackPointer;
929 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +0000930
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000931 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +0000932 return false;
933 }
934 return true;
935}
936
937// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +0000938// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000939bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000940EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +0000941{
942#if 0
943 // ARM pseudo code...
944 if (ConditionPassed())
945 {
946 EncodingSpecificOperations();
947 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
948 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
949 if d == 15 then
950 ALUWritePC(result); // setflags is always FALSE here
951 else
952 R[d] = result;
953 if setflags then
954 APSR.N = result<31>;
955 APSR.Z = IsZeroBit(result);
956 APSR.C = carry;
957 APSR.V = overflow;
958 }
959#endif
960
961 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000962 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000963 if (!success)
964 return false;
965
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000966 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +0000967 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000968 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000969 if (!success)
970 return false;
971 uint32_t Rm; // the second operand
972 switch (encoding) {
973 case eEncodingT2:
974 Rm = Bits32(opcode, 6, 3);
975 break;
976 default:
977 return false;
978 }
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000979 int32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +0000980 if (!success)
981 return false;
982
983 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
984
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000985 EmulateInstruction::Context context;
986 context.type = EmulateInstruction::eContextAdjustStackPointer;
987 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +0000988
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000989 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +0000990 return false;
991 }
992 return true;
993}
994
Johnny Chen9b8d7832011-02-02 01:13:56 +0000995// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
996// at a PC-relative address, and changes instruction set from ARM to Thumb, or
997// from Thumb to ARM.
998// BLX (immediate)
999bool
1000EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1001{
1002#if 0
1003 // ARM pseudo code...
1004 if (ConditionPassed())
1005 {
1006 EncodingSpecificOperations();
1007 if CurrentInstrSet() == InstrSet_ARM then
1008 LR = PC - 4;
1009 else
1010 LR = PC<31:1> : '1';
1011 if targetInstrSet == InstrSet_ARM then
1012 targetAddress = Align(PC,4) + imm32;
1013 else
1014 targetAddress = PC + imm32;
1015 SelectInstrSet(targetInstrSet);
1016 BranchWritePC(targetAddress);
1017 }
1018#endif
1019
1020 bool success = false;
1021 const uint32_t opcode = OpcodeAsUnsigned (&success);
1022 if (!success)
1023 return false;
1024
1025 if (ConditionPassed())
1026 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001027 EmulateInstruction::Context context;
1028 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001029 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001030 if (!success)
1031 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001032 addr_t lr; // next instruction address
1033 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001034 int32_t imm32; // PC-relative offset
1035 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001036 case eEncodingT1:
1037 {
1038 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001039 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001040 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001041 uint32_t J1 = Bit32(opcode, 13);
1042 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001043 uint32_t imm11 = Bits32(opcode, 10, 0);
1044 uint32_t I1 = !(J1 ^ S);
1045 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001046 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001047 imm32 = llvm::SignExtend32<25>(imm25);
1048 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001049 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001050 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001051 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001052 break;
1053 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001054 case eEncodingT2:
1055 {
1056 lr = (pc + 4) | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001057 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001058 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001059 uint32_t J1 = Bit32(opcode, 13);
1060 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001061 uint32_t imm10L = Bits32(opcode, 10, 1);
1062 uint32_t I1 = !(J1 ^ S);
1063 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001064 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001065 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chend6c13f02011-02-08 20:36:34 +00001066 target = Align(pc + 4, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001067 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001068 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001069 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001070 break;
1071 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001072 case eEncodingA1:
1073 lr = pc + 4; // return address
1074 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chend6c13f02011-02-08 20:36:34 +00001075 target = Align(pc + 8, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001076 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001077 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001078 case eEncodingA2:
1079 lr = pc + 4; // return address
1080 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1081 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001082 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001083 break;
1084 default:
1085 return false;
1086 }
1087 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1088 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001089 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001090 return false;
1091 }
1092 return true;
1093}
1094
1095// Branch with Link and Exchange (register) calls a subroutine at an address and
1096// instruction set specified by a register.
1097// BLX (register)
1098bool
1099EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1100{
1101#if 0
1102 // ARM pseudo code...
1103 if (ConditionPassed())
1104 {
1105 EncodingSpecificOperations();
1106 target = R[m];
1107 if CurrentInstrSet() == InstrSet_ARM then
1108 next_instr_addr = PC - 4;
1109 LR = next_instr_addr;
1110 else
1111 next_instr_addr = PC - 2;
1112 LR = next_instr_addr<31:1> : ‘1’;
1113 BXWritePC(target);
1114 }
1115#endif
1116
1117 bool success = false;
1118 const uint32_t opcode = OpcodeAsUnsigned (&success);
1119 if (!success)
1120 return false;
1121
1122 if (ConditionPassed())
1123 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001124 EmulateInstruction::Context context;
1125 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001126 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1127 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001128 if (!success)
1129 return false;
1130 uint32_t Rm; // the register with the target address
1131 switch (encoding) {
1132 case eEncodingT1:
1133 lr = (pc + 2) | 1u; // return address
1134 Rm = Bits32(opcode, 6, 3);
1135 // if m == 15 then UNPREDICTABLE;
1136 if (Rm == 15)
1137 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001138 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001139 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001140 break;
1141 case eEncodingA1:
1142 lr = pc + 4; // return address
1143 Rm = Bits32(opcode, 3, 0);
1144 // if m == 15 then UNPREDICTABLE;
1145 if (Rm == 15)
1146 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001147 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001148 default:
1149 return false;
1150 }
Johnny Chenab3b3512011-02-12 00:10:51 +00001151 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1152 if (!success)
1153 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001154 Register dwarf_reg;
1155 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1156 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001157 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1158 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001159 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001160 return false;
1161 }
1162 return true;
1163}
1164
Johnny Chenab3b3512011-02-12 00:10:51 +00001165// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1166// BX
1167bool
1168EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1169{
1170#if 0
1171 // ARM pseudo code...
1172 if (ConditionPassed())
1173 {
1174 EncodingSpecificOperations();
1175 BXWritePC(R[m]);
1176 }
1177#endif
1178
1179 bool success = false;
1180 const uint32_t opcode = OpcodeAsUnsigned (&success);
1181 if (!success)
1182 return false;
1183
1184 if (ConditionPassed())
1185 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001186 EmulateInstruction::Context context;
1187 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001188 uint32_t Rm; // the register with the target address
1189 switch (encoding) {
1190 case eEncodingT1:
1191 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001192 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001193 return false;
1194 break;
1195 case eEncodingA1:
1196 Rm = Bits32(opcode, 3, 0);
1197 break;
1198 default:
1199 return false;
1200 }
1201 addr_t target = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1202 if (!success)
1203 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001204
1205 Register dwarf_reg;
1206 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001207 context.SetRegister (dwarf_reg);
1208 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001209 return false;
1210 }
1211 return true;
1212}
1213
Johnny Chen0d0148e2011-01-28 02:26:08 +00001214// Set r7 to point to some ip offset.
1215// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001216bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001217EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001218{
1219#if 0
1220 // ARM pseudo code...
1221 if (ConditionPassed())
1222 {
1223 EncodingSpecificOperations();
1224 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1225 if d == 15 then // Can only occur for ARM encoding
1226 ALUWritePC(result); // setflags is always FALSE here
1227 else
1228 R[d] = result;
1229 if setflags then
1230 APSR.N = result<31>;
1231 APSR.Z = IsZeroBit(result);
1232 APSR.C = carry;
1233 APSR.V = overflow;
1234 }
1235#endif
1236
1237 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001238 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001239 if (!success)
1240 return false;
1241
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001242 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001243 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001244 const addr_t ip = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r12, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001245 if (!success)
1246 return false;
1247 uint32_t imm32;
1248 switch (encoding) {
1249 case eEncodingA1:
1250 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1251 break;
1252 default:
1253 return false;
1254 }
1255 addr_t ip_offset = imm32;
1256 addr_t addr = ip - ip_offset; // the adjusted ip value
1257
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001258 EmulateInstruction::Context context;
1259 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1260 Register dwarf_reg;
1261 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1262 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001263
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001264 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001265 return false;
1266 }
1267 return true;
1268}
1269
1270// Set ip to point to some stack offset.
1271// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001272bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001273EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001274{
1275#if 0
1276 // ARM pseudo code...
1277 if (ConditionPassed())
1278 {
1279 EncodingSpecificOperations();
1280 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1281 if d == 15 then // Can only occur for ARM encoding
1282 ALUWritePC(result); // setflags is always FALSE here
1283 else
1284 R[d] = result;
1285 if setflags then
1286 APSR.N = result<31>;
1287 APSR.Z = IsZeroBit(result);
1288 APSR.C = carry;
1289 APSR.V = overflow;
1290 }
1291#endif
1292
1293 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001294 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001295 if (!success)
1296 return false;
1297
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001298 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001299 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001300 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001301 if (!success)
1302 return false;
1303 uint32_t imm32;
1304 switch (encoding) {
1305 case eEncodingA1:
1306 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1307 break;
1308 default:
1309 return false;
1310 }
1311 addr_t sp_offset = imm32;
1312 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1313
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001314 EmulateInstruction::Context context;
1315 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1316 Register dwarf_reg;
1317 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1318 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001319
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001320 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001321 return false;
1322 }
1323 return true;
1324}
1325
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001326// A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001327bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001328EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001329{
1330#if 0
1331 // ARM pseudo code...
1332 if (ConditionPassed())
1333 {
1334 EncodingSpecificOperations();
1335 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1336 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001337 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001338 else
1339 R[d] = result;
1340 if setflags then
1341 APSR.N = result<31>;
1342 APSR.Z = IsZeroBit(result);
1343 APSR.C = carry;
1344 APSR.V = overflow;
1345 }
1346#endif
1347
1348 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001349 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001350 if (!success)
1351 return false;
1352
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001353 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001354 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001355 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001356 if (!success)
1357 return false;
1358 uint32_t imm32;
1359 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001360 case eEncodingT1:
1361 imm32 = ThumbImmScaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chen60c0d622011-01-25 23:49:39 +00001362 case eEncodingT2:
1363 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1364 break;
1365 case eEncodingT3:
1366 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1367 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001368 case eEncodingA1:
Johnny Chen60c0d622011-01-25 23:49:39 +00001369 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001370 break;
1371 default:
1372 return false;
1373 }
1374 addr_t sp_offset = imm32;
1375 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1376
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001377 EmulateInstruction::Context context;
1378 context.type = EmulateInstruction::eContextAdjustStackPointer;
1379 context.SetImmediateSigned (-sp_offset);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001380
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001381 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001382 return false;
1383 }
1384 return true;
1385}
1386
Johnny Chen08c25e82011-01-31 18:02:28 +00001387// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001388bool
1389EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001390{
1391#if 0
1392 // ARM pseudo code...
1393 if (ConditionPassed())
1394 {
1395 EncodingSpecificOperations();
1396 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1397 address = if index then offset_addr else R[n];
1398 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1399 if wback then R[n] = offset_addr;
1400 }
1401#endif
1402
1403 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001404 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001405 if (!success)
1406 return false;
1407
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001408 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001409 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001410 const uint32_t addr_byte_size = GetAddressByteSize();
1411 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001412 if (!success)
1413 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001414 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001415 uint32_t imm12;
1416 switch (encoding) {
1417 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001418 Rt = Bits32(opcode, 15, 12);
1419 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001420 break;
1421 default:
1422 return false;
1423 }
1424 addr_t sp_offset = imm12;
1425 addr_t addr = sp - sp_offset;
1426
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001427 EmulateInstruction::Context context;
1428 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1429 Register dwarf_reg;
1430 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001431 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001432 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001433 dwarf_reg.num = dwarf_r0 + Rt;
1434 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
1435 uint32_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001436 if (!success)
1437 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001438 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001439 return false;
1440 }
1441 else
1442 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001443 dwarf_reg.num = dwarf_pc;
1444 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001445 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001446 if (!success)
1447 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001448 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001449 return false;
1450 }
1451
1452 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001453 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001454
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001455 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001456 return false;
1457 }
1458 return true;
1459}
1460
Johnny Chen08c25e82011-01-31 18:02:28 +00001461// Vector Push stores multiple extension registers to the stack.
1462// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001463bool
1464EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001465{
1466#if 0
1467 // ARM pseudo code...
1468 if (ConditionPassed())
1469 {
1470 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1471 address = SP - imm32;
1472 SP = SP - imm32;
1473 if single_regs then
1474 for r = 0 to regs-1
1475 MemA[address,4] = S[d+r]; address = address+4;
1476 else
1477 for r = 0 to regs-1
1478 // Store as two word-aligned words in the correct order for current endianness.
1479 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1480 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1481 address = address+8;
1482 }
1483#endif
1484
1485 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001486 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001487 if (!success)
1488 return false;
1489
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001490 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001491 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001492 const uint32_t addr_byte_size = GetAddressByteSize();
1493 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001494 if (!success)
1495 return false;
1496 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001497 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001498 uint32_t imm32; // stack offset
1499 uint32_t regs; // number of registers
1500 switch (encoding) {
1501 case eEncodingT1:
1502 case eEncodingA1:
1503 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001504 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001505 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1506 // If UInt(imm8) is odd, see "FSTMX".
1507 regs = Bits32(opcode, 7, 0) / 2;
1508 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1509 if (regs == 0 || regs > 16 || (d + regs) > 32)
1510 return false;
1511 break;
1512 case eEncodingT2:
1513 case eEncodingA2:
1514 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001515 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001516 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1517 regs = Bits32(opcode, 7, 0);
1518 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1519 if (regs == 0 || regs > 16 || (d + regs) > 32)
1520 return false;
1521 break;
1522 default:
1523 return false;
1524 }
1525 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1526 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1527 addr_t sp_offset = imm32;
1528 addr_t addr = sp - sp_offset;
1529 uint32_t i;
1530
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001531 EmulateInstruction::Context context;
1532 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1533 Register dwarf_reg;
1534 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001535 for (i=d; i<regs; ++i)
1536 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001537 dwarf_reg.num = start_reg + i;
1538 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001539 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001540 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001541 if (!success)
1542 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001543 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001544 return false;
1545 addr += reg_byte_size;
1546 }
1547
1548 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001549 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001550
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001551 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001552 return false;
1553 }
1554 return true;
1555}
1556
Johnny Chen587a0a42011-02-01 18:35:28 +00001557// Vector Pop loads multiple extension registers from the stack.
1558// It also updates SP to point just above the loaded data.
1559bool
1560EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1561{
1562#if 0
1563 // ARM pseudo code...
1564 if (ConditionPassed())
1565 {
1566 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1567 address = SP;
1568 SP = SP + imm32;
1569 if single_regs then
1570 for r = 0 to regs-1
1571 S[d+r] = MemA[address,4]; address = address+4;
1572 else
1573 for r = 0 to regs-1
1574 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1575 // Combine the word-aligned words in the correct order for current endianness.
1576 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1577 }
1578#endif
1579
1580 bool success = false;
1581 const uint32_t opcode = OpcodeAsUnsigned (&success);
1582 if (!success)
1583 return false;
1584
1585 if (ConditionPassed())
1586 {
1587 const uint32_t addr_byte_size = GetAddressByteSize();
1588 const addr_t sp = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, 0, &success);
1589 if (!success)
1590 return false;
1591 bool single_regs;
1592 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1593 uint32_t imm32; // stack offset
1594 uint32_t regs; // number of registers
1595 switch (encoding) {
1596 case eEncodingT1:
1597 case eEncodingA1:
1598 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001599 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001600 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1601 // If UInt(imm8) is odd, see "FLDMX".
1602 regs = Bits32(opcode, 7, 0) / 2;
1603 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1604 if (regs == 0 || regs > 16 || (d + regs) > 32)
1605 return false;
1606 break;
1607 case eEncodingT2:
1608 case eEncodingA2:
1609 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001610 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001611 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1612 regs = Bits32(opcode, 7, 0);
1613 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1614 if (regs == 0 || regs > 16 || (d + regs) > 32)
1615 return false;
1616 break;
1617 default:
1618 return false;
1619 }
1620 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1621 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1622 addr_t sp_offset = imm32;
1623 addr_t addr = sp;
1624 uint32_t i;
1625 uint64_t data; // uint64_t to accomodate 64-bit registers.
1626
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001627 EmulateInstruction::Context context;
1628 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1629 Register dwarf_reg;
1630 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001631 for (i=d; i<regs; ++i)
1632 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001633 dwarf_reg.num = start_reg + i;
1634 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001635 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001636 if (!success)
1637 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001638 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001639 return false;
1640 addr += reg_byte_size;
1641 }
1642
1643 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001644 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001645
1646 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1647 return false;
1648 }
1649 return true;
1650}
1651
Johnny Chenb77be412011-02-04 00:40:18 +00001652// SVC (previously SWI)
1653bool
1654EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1655{
1656#if 0
1657 // ARM pseudo code...
1658 if (ConditionPassed())
1659 {
1660 EncodingSpecificOperations();
1661 CallSupervisor();
1662 }
1663#endif
1664
1665 bool success = false;
1666 const uint32_t opcode = OpcodeAsUnsigned (&success);
1667 if (!success)
1668 return false;
1669
1670 if (ConditionPassed())
1671 {
1672 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1673 addr_t lr; // next instruction address
1674 if (!success)
1675 return false;
1676 uint32_t imm32; // the immediate constant
1677 uint32_t mode; // ARM or Thumb mode
1678 switch (encoding) {
1679 case eEncodingT1:
1680 lr = (pc + 2) | 1u; // return address
1681 imm32 = Bits32(opcode, 7, 0);
1682 mode = eModeThumb;
1683 break;
1684 case eEncodingA1:
1685 lr = pc + 4; // return address
1686 imm32 = Bits32(opcode, 23, 0);
1687 mode = eModeARM;
1688 break;
1689 default:
1690 return false;
1691 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001692
1693 EmulateInstruction::Context context;
1694 context.type = EmulateInstruction::eContextSupervisorCall;
1695 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001696 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1697 return false;
1698 }
1699 return true;
1700}
1701
Johnny Chenc315f862011-02-05 00:46:10 +00001702// If Then makes up to four following instructions (the IT block) conditional.
1703bool
1704EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1705{
1706#if 0
1707 // ARM pseudo code...
1708 EncodingSpecificOperations();
1709 ITSTATE.IT<7:0> = firstcond:mask;
1710#endif
1711
1712 bool success = false;
1713 const uint32_t opcode = OpcodeAsUnsigned (&success);
1714 if (!success)
1715 return false;
1716
1717 m_it_session.InitIT(Bits32(opcode, 7, 0));
1718 return true;
1719}
1720
Johnny Chen3b620b32011-02-07 20:11:47 +00001721// Branch causes a branch to a target address.
1722bool
1723EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1724{
1725#if 0
1726 // ARM pseudo code...
1727 if (ConditionPassed())
1728 {
1729 EncodingSpecificOperations();
1730 BranchWritePC(PC + imm32);
1731 }
1732#endif
1733
1734 bool success = false;
1735 const uint32_t opcode = OpcodeAsUnsigned (&success);
1736 if (!success)
1737 return false;
1738
Johnny Chen9ee056b2011-02-08 00:06:35 +00001739 if (ConditionPassed())
1740 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001741 EmulateInstruction::Context context;
1742 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001743 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001744 if (!success)
1745 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001746 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001747 int32_t imm32; // PC-relative offset
1748 switch (encoding) {
1749 case eEncodingT1:
1750 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1751 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
1752 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001753 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001754 break;
1755 case eEncodingT2:
1756 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
1757 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001758 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001759 break;
1760 case eEncodingT3:
1761 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1762 {
Johnny Chenbd599902011-02-10 21:39:01 +00001763 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001764 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001765 uint32_t J1 = Bit32(opcode, 13);
1766 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001767 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001768 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001769 imm32 = llvm::SignExtend32<21>(imm21);
1770 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001771 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001772 break;
1773 }
1774 case eEncodingT4:
1775 {
Johnny Chenbd599902011-02-10 21:39:01 +00001776 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001777 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001778 uint32_t J1 = Bit32(opcode, 13);
1779 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001780 uint32_t imm11 = Bits32(opcode, 10, 0);
1781 uint32_t I1 = !(J1 ^ S);
1782 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001783 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001784 imm32 = llvm::SignExtend32<25>(imm25);
1785 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001786 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001787 break;
1788 }
1789 case eEncodingA1:
1790 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1791 target = pc + 8 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001792 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001793 break;
1794 default:
1795 return false;
1796 }
1797 if (!BranchWritePC(context, target))
1798 return false;
1799 }
1800 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001801}
1802
Johnny Chen53ebab72011-02-08 23:21:57 +00001803// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1804// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1805// CBNZ, CBZ
1806bool
1807EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1808{
1809#if 0
1810 // ARM pseudo code...
1811 EncodingSpecificOperations();
1812 if nonzero ^ IsZero(R[n]) then
1813 BranchWritePC(PC + imm32);
1814#endif
1815
1816 bool success = false;
1817 const uint32_t opcode = OpcodeAsUnsigned (&success);
1818 if (!success)
1819 return false;
1820
1821 // Read the register value from the operand register Rn.
1822 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Bits32(opcode, 2, 0), 0, &success);
1823 if (!success)
1824 return false;
1825
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001826 EmulateInstruction::Context context;
1827 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chen53ebab72011-02-08 23:21:57 +00001828 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1829 if (!success)
1830 return false;
1831
1832 addr_t target; // target address
1833 uint32_t imm32; // PC-relative offset to branch forward
1834 bool nonzero;
1835 switch (encoding) {
1836 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00001837 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00001838 nonzero = BitIsSet(opcode, 11);
1839 target = pc + 4 + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001840 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00001841 break;
1842 default:
1843 return false;
1844 }
1845 if (nonzero ^ (reg_val == 0))
1846 if (!BranchWritePC(context, target))
1847 return false;
1848
1849 return true;
1850}
1851
Johnny Chen60299ec2011-02-17 19:34:27 +00001852// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
1853// A base register provides a pointer to the table, and a second register supplies an index into the table.
1854// The branch length is twice the value of the byte returned from the table.
1855//
1856// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
1857// A base register provides a pointer to the table, and a second register supplies an index into the table.
1858// The branch length is twice the value of the halfword returned from the table.
1859// TBB, TBH
1860bool
1861EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
1862{
1863#if 0
1864 // ARM pseudo code...
1865 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
1866 if is_tbh then
1867 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
1868 else
1869 halfwords = UInt(MemU[R[n]+R[m], 1]);
1870 BranchWritePC(PC + 2*halfwords);
1871#endif
1872
1873 bool success = false;
1874 const uint32_t opcode = OpcodeAsUnsigned (&success);
1875 if (!success)
1876 return false;
1877
1878 uint32_t Rn; // the base register which contains the address of the table of branch lengths
1879 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
1880 bool is_tbh; // true if table branch halfword
1881 switch (encoding) {
1882 case eEncodingT1:
1883 Rn = Bits32(opcode, 19, 16);
1884 Rm = Bits32(opcode, 3, 0);
1885 is_tbh = BitIsSet(opcode, 4);
1886 if (Rn == 13 || BadReg(Rm))
1887 return false;
1888 if (InITBlock() && !LastInITBlock())
1889 return false;
1890 break;
1891 default:
1892 return false;
1893 }
1894
1895 // Read the address of the table from the operand register Rn.
1896 // The PC can be used, in which case the table immediately follows this instruction.
1897 uint32_t base =
1898 Rn == 15 ? (ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success) + 4)
1899 : ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
1900 if (!success)
1901 return false;
1902
1903 // the table index
1904 uint32_t index = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
1905 if (!success)
1906 return false;
1907
1908 // the offsetted table address
1909 addr_t addr = base + (is_tbh ? index*2 : index);
1910
1911 // PC-relative offset to branch forward
1912 EmulateInstruction::Context context;
1913 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00001914 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00001915 if (!success)
1916 return false;
1917
1918 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1919 if (!success)
1920 return false;
1921
1922 // target address
1923 addr_t target = pc + 4 + offset;
1924 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1925 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
1926
1927 if (!BranchWritePC(context, target))
1928 return false;
1929
1930 return true;
1931}
1932
Johnny Chen8fa20592011-02-18 01:22:22 +00001933// This instruction adds an immediate value to a register value, and writes the result to the destination
1934// register. It can optionally update the condition flags based on the result.
1935bool
1936EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
1937{
1938#if 0
1939 // ARM pseudo code...
1940 if ConditionPassed() then
1941 EncodingSpecificOperations();
1942 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1943 if d == 15 then
1944 ALUWritePC(result); // setflags is always FALSE here
1945 else
1946 R[d] = result;
1947 if setflags then
1948 APSR.N = result<31>;
1949 APSR.Z = IsZeroBit(result);
1950 APSR.C = carry;
1951 APSR.V = overflow;
1952#endif
1953
1954 bool success = false;
1955 const uint32_t opcode = OpcodeAsUnsigned (&success);
1956 if (!success)
1957 return false;
1958
1959 if (ConditionPassed())
1960 {
1961 uint32_t Rd, Rn;
1962 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
1963 bool setflags;
1964 switch (encoding)
1965 {
1966 case eEncodingA1:
1967 Rd = Bits32(opcode, 15, 12);
1968 Rn = Bits32(opcode, 19, 16);
1969 setflags = BitIsSet(opcode, 20);
1970 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1971 break;
1972 default:
1973 return false;
1974 }
1975
Johnny Chen8fa20592011-02-18 01:22:22 +00001976 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00001977 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00001978 if (!success)
1979 return false;
1980
1981 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
1982
1983 EmulateInstruction::Context context;
1984 context.type = EmulateInstruction::eContextImmediate;
1985 context.SetNoArgs ();
1986
1987 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1988 return false;
1989 }
1990 return true;
1991}
1992
Johnny Chend761dcf2011-02-17 22:03:29 +00001993// This instruction adds a register value and an optionally-shifted register value, and writes the result
1994// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00001995bool
Johnny Chen9f687722011-02-18 00:02:28 +00001996EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00001997{
1998#if 0
1999 // ARM pseudo code...
2000 if ConditionPassed() then
2001 EncodingSpecificOperations();
2002 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2003 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2004 if d == 15 then
2005 ALUWritePC(result); // setflags is always FALSE here
2006 else
2007 R[d] = result;
2008 if setflags then
2009 APSR.N = result<31>;
2010 APSR.Z = IsZeroBit(result);
2011 APSR.C = carry;
2012 APSR.V = overflow;
2013#endif
2014
2015 bool success = false;
2016 const uint32_t opcode = OpcodeAsUnsigned (&success);
2017 if (!success)
2018 return false;
2019
2020 if (ConditionPassed())
2021 {
2022 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002023 ARM_ShifterType shift_t;
2024 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002025 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002026 switch (encoding)
2027 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002028 case eEncodingT1:
2029 Rd = Bits32(opcode, 2, 0);
2030 Rn = Bits32(opcode, 5, 3);
2031 Rm = Bits32(opcode, 8, 6);
2032 setflags = !InITBlock();
2033 shift_t = SRType_LSL;
2034 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002035 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002036 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002037 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002038 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002039 shift_t = SRType_LSL;
2040 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002041 if (Rn == 15 && Rm == 15)
2042 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002043 if (Rd == 15 && InITBlock() && !LastInITBlock())
2044 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002045 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002046 case eEncodingA1:
2047 Rd = Bits32(opcode, 15, 12);
2048 Rn = Bits32(opcode, 19, 16);
2049 Rm = Bits32(opcode, 3, 0);
2050 setflags = BitIsSet(opcode, 20);
2051 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
2052 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002053 default:
2054 return false;
2055 }
2056
Johnny Chen26863dc2011-02-09 23:43:29 +00002057 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002058 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002059 if (!success)
2060 return false;
2061
2062 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002063 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002064 if (!success)
2065 return false;
2066
Johnny Chene97c0d52011-02-18 19:32:20 +00002067 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002068 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002069
2070 EmulateInstruction::Context context;
2071 context.type = EmulateInstruction::eContextImmediate;
2072 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002073
Johnny Chen10530c22011-02-17 22:37:12 +00002074 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002075 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002076 }
2077 return true;
2078}
2079
Johnny Chene4a4d302011-02-11 21:53:58 +00002080// CMP (immediate)
Johnny Chend4dc4442011-02-11 02:02:56 +00002081bool
Johnny Chen9f687722011-02-18 00:02:28 +00002082EmulateInstructionARM::EmulateCMPRnImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002083{
2084#if 0
2085 // ARM pseudo code...
2086 if ConditionPassed() then
2087 EncodingSpecificOperations();
2088 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2089 APSR.N = result<31>;
2090 APSR.Z = IsZeroBit(result);
2091 APSR.C = carry;
2092 APSR.V = overflow;
2093#endif
2094
2095 bool success = false;
2096 const uint32_t opcode = OpcodeAsUnsigned (&success);
2097 if (!success)
2098 return false;
2099
2100 uint32_t Rn; // the first operand
2101 uint32_t imm32; // the immediate value to be compared with
2102 switch (encoding) {
2103 case eEncodingT1:
2104 Rn = Bits32(opcode, 10, 8);
2105 imm32 = Bits32(opcode, 7, 0);
2106 break;
2107 default:
2108 return false;
2109 }
2110 // Read the register value from the operand register Rn.
2111 uint32_t reg_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2112 if (!success)
2113 return false;
2114
Johnny Chen10530c22011-02-17 22:37:12 +00002115 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2116
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002117 EmulateInstruction::Context context;
2118 context.type = EmulateInstruction::eContextImmediate;
2119 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002120 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2121 return false;
2122
Johnny Chend4dc4442011-02-11 02:02:56 +00002123 return true;
2124}
2125
Johnny Chene4a4d302011-02-11 21:53:58 +00002126// CMP (register)
2127bool
Johnny Chen9f687722011-02-18 00:02:28 +00002128EmulateInstructionARM::EmulateCMPRnRm (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002129{
2130#if 0
2131 // ARM pseudo code...
2132 if ConditionPassed() then
2133 EncodingSpecificOperations();
2134 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2135 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2136 APSR.N = result<31>;
2137 APSR.Z = IsZeroBit(result);
2138 APSR.C = carry;
2139 APSR.V = overflow;
2140#endif
2141
2142 bool success = false;
2143 const uint32_t opcode = OpcodeAsUnsigned (&success);
2144 if (!success)
2145 return false;
2146
2147 uint32_t Rn; // the first operand
2148 uint32_t Rm; // the second operand
2149 switch (encoding) {
2150 case eEncodingT1:
2151 Rn = Bits32(opcode, 2, 0);
2152 Rm = Bits32(opcode, 5, 3);
2153 break;
2154 case eEncodingT2:
2155 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2156 Rm = Bits32(opcode, 6, 3);
2157 if (Rn < 8 && Rm < 8)
2158 return false;
2159 if (Rn == 15 || Rm == 15)
2160 return false;
2161 break;
2162 default:
2163 return false;
2164 }
2165 // Read the register value from register Rn.
2166 uint32_t reg_val1 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2167 if (!success)
2168 return false;
2169 // Read the register value from register Rm.
2170 // The register value is not being shifted since we don't handle ARM for now.
2171 uint32_t reg_val2 = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2172 if (!success)
2173 return false;
2174
Johnny Chen10530c22011-02-17 22:37:12 +00002175 AddWithCarryResult res = AddWithCarry(reg_val1, ~reg_val2, 1);
2176
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002177 EmulateInstruction::Context context;
2178 context.type = EmulateInstruction::eContextImmediate;
2179 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002180 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2181 return false;
2182
Johnny Chene4a4d302011-02-11 21:53:58 +00002183 return true;
2184}
2185
Johnny Chen82f16aa2011-02-15 20:10:55 +00002186// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2187// shifting in copies of its sign bit, and writes the result to the destination register. It can
2188// optionally update the condition flags based on the result.
2189bool
2190EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2191{
2192#if 0
2193 // ARM pseudo code...
2194 if ConditionPassed() then
2195 EncodingSpecificOperations();
2196 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2197 if d == 15 then // Can only occur for ARM encoding
2198 ALUWritePC(result); // setflags is always FALSE here
2199 else
2200 R[d] = result;
2201 if setflags then
2202 APSR.N = result<31>;
2203 APSR.Z = IsZeroBit(result);
2204 APSR.C = carry;
2205 // APSR.V unchanged
2206#endif
2207
Johnny Chen41a0a152011-02-16 01:27:54 +00002208 return EmulateShiftImm(encoding, SRType_ASR);
2209}
2210
2211// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2212// shifting in copies of its sign bit, and writes the result to the destination register.
2213// The variable number of bits is read from the bottom byte of a register. It can optionally update
2214// the condition flags based on the result.
2215bool
2216EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2217{
2218#if 0
2219 // ARM pseudo code...
2220 if ConditionPassed() then
2221 EncodingSpecificOperations();
2222 shift_n = UInt(R[m]<7:0>);
2223 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2224 R[d] = result;
2225 if setflags then
2226 APSR.N = result<31>;
2227 APSR.Z = IsZeroBit(result);
2228 APSR.C = carry;
2229 // APSR.V unchanged
2230#endif
2231
2232 return EmulateShiftReg(encoding, SRType_ASR);
2233}
2234
2235// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2236// shifting in zeros, and writes the result to the destination register. It can optionally
2237// update the condition flags based on the result.
2238bool
2239EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2240{
2241#if 0
2242 // ARM pseudo code...
2243 if ConditionPassed() then
2244 EncodingSpecificOperations();
2245 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2246 if d == 15 then // Can only occur for ARM encoding
2247 ALUWritePC(result); // setflags is always FALSE here
2248 else
2249 R[d] = result;
2250 if setflags then
2251 APSR.N = result<31>;
2252 APSR.Z = IsZeroBit(result);
2253 APSR.C = carry;
2254 // APSR.V unchanged
2255#endif
2256
2257 return EmulateShiftImm(encoding, SRType_LSL);
2258}
2259
2260// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2261// shifting in zeros, and writes the result to the destination register. The variable number
2262// of bits is read from the bottom byte of a register. It can optionally update the condition
2263// flags based on the result.
2264bool
2265EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2266{
2267#if 0
2268 // ARM pseudo code...
2269 if ConditionPassed() then
2270 EncodingSpecificOperations();
2271 shift_n = UInt(R[m]<7:0>);
2272 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2273 R[d] = result;
2274 if setflags then
2275 APSR.N = result<31>;
2276 APSR.Z = IsZeroBit(result);
2277 APSR.C = carry;
2278 // APSR.V unchanged
2279#endif
2280
2281 return EmulateShiftReg(encoding, SRType_LSL);
2282}
2283
2284// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2285// shifting in zeros, and writes the result to the destination register. It can optionally
2286// update the condition flags based on the result.
2287bool
2288EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2289{
2290#if 0
2291 // ARM pseudo code...
2292 if ConditionPassed() then
2293 EncodingSpecificOperations();
2294 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2295 if d == 15 then // Can only occur for ARM encoding
2296 ALUWritePC(result); // setflags is always FALSE here
2297 else
2298 R[d] = result;
2299 if setflags then
2300 APSR.N = result<31>;
2301 APSR.Z = IsZeroBit(result);
2302 APSR.C = carry;
2303 // APSR.V unchanged
2304#endif
2305
2306 return EmulateShiftImm(encoding, SRType_LSR);
2307}
2308
2309// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2310// shifting in zeros, and writes the result to the destination register. The variable number
2311// of bits is read from the bottom byte of a register. It can optionally update the condition
2312// flags based on the result.
2313bool
2314EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2315{
2316#if 0
2317 // ARM pseudo code...
2318 if ConditionPassed() then
2319 EncodingSpecificOperations();
2320 shift_n = UInt(R[m]<7:0>);
2321 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2322 R[d] = result;
2323 if setflags then
2324 APSR.N = result<31>;
2325 APSR.Z = IsZeroBit(result);
2326 APSR.C = carry;
2327 // APSR.V unchanged
2328#endif
2329
2330 return EmulateShiftReg(encoding, SRType_LSR);
2331}
2332
Johnny Cheneeab4852011-02-16 22:14:44 +00002333// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2334// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2335// It can optionally update the condition flags based on the result.
2336bool
2337EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2338{
2339#if 0
2340 // ARM pseudo code...
2341 if ConditionPassed() then
2342 EncodingSpecificOperations();
2343 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2344 if d == 15 then // Can only occur for ARM encoding
2345 ALUWritePC(result); // setflags is always FALSE here
2346 else
2347 R[d] = result;
2348 if setflags then
2349 APSR.N = result<31>;
2350 APSR.Z = IsZeroBit(result);
2351 APSR.C = carry;
2352 // APSR.V unchanged
2353#endif
2354
2355 return EmulateShiftImm(encoding, SRType_ROR);
2356}
2357
2358// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2359// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2360// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2361// flags based on the result.
2362bool
2363EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2364{
2365#if 0
2366 // ARM pseudo code...
2367 if ConditionPassed() then
2368 EncodingSpecificOperations();
2369 shift_n = UInt(R[m]<7:0>);
2370 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2371 R[d] = result;
2372 if setflags then
2373 APSR.N = result<31>;
2374 APSR.Z = IsZeroBit(result);
2375 APSR.C = carry;
2376 // APSR.V unchanged
2377#endif
2378
2379 return EmulateShiftReg(encoding, SRType_ROR);
2380}
2381
2382// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2383// with the carry flag shifted into bit [31].
2384//
2385// RRX can optionally update the condition flags based on the result.
2386// In that case, bit [0] is shifted into the carry flag.
2387bool
2388EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2389{
2390#if 0
2391 // ARM pseudo code...
2392 if ConditionPassed() then
2393 EncodingSpecificOperations();
2394 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2395 if d == 15 then // Can only occur for ARM encoding
2396 ALUWritePC(result); // setflags is always FALSE here
2397 else
2398 R[d] = result;
2399 if setflags then
2400 APSR.N = result<31>;
2401 APSR.Z = IsZeroBit(result);
2402 APSR.C = carry;
2403 // APSR.V unchanged
2404#endif
2405
2406 return EmulateShiftImm(encoding, SRType_RRX);
2407}
2408
Johnny Chen41a0a152011-02-16 01:27:54 +00002409bool
2410EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2411{
2412 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2413
Johnny Chen82f16aa2011-02-15 20:10:55 +00002414 bool success = false;
2415 const uint32_t opcode = OpcodeAsUnsigned (&success);
2416 if (!success)
2417 return false;
2418
2419 if (ConditionPassed())
2420 {
Johnny Chene7f89532011-02-15 23:22:46 +00002421 uint32_t Rd; // the destination register
2422 uint32_t Rm; // the first operand register
2423 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002424 uint32_t carry; // the carry bit after the shift operation
2425 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002426
2427 // Special case handling!
2428 // A8.6.139 ROR (immediate) -- Encoding T1
2429 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2430 {
2431 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2432 // have the same decoding of bit fields as the other Thumb2 shift operations.
2433 encoding = eEncodingT2;
2434 }
2435
Johnny Chen82f16aa2011-02-15 20:10:55 +00002436 switch (encoding) {
2437 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002438 // Due to the above special case handling!
2439 assert(shift_type != SRType_ROR);
2440
Johnny Chen82f16aa2011-02-15 20:10:55 +00002441 Rd = Bits32(opcode, 2, 0);
2442 Rm = Bits32(opcode, 5, 3);
2443 setflags = !InITBlock();
2444 imm5 = Bits32(opcode, 10, 6);
2445 break;
2446 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002447 // A8.6.141 RRX
2448 assert(shift_type != SRType_RRX);
2449
Johnny Chen82f16aa2011-02-15 20:10:55 +00002450 Rd = Bits32(opcode, 11, 8);
2451 Rm = Bits32(opcode, 3, 0);
2452 setflags = BitIsSet(opcode, 20);
2453 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2454 if (BadReg(Rd) || BadReg(Rm))
2455 return false;
2456 break;
2457 case eEncodingA1:
2458 Rd = Bits32(opcode, 15, 12);
2459 Rm = Bits32(opcode, 3, 0);
2460 setflags = BitIsSet(opcode, 20);
2461 imm5 = Bits32(opcode, 11, 7);
2462 break;
2463 default:
2464 return false;
2465 }
2466
Johnny Cheneeab4852011-02-16 22:14:44 +00002467 // A8.6.139 ROR (immediate)
2468 if (shift_type == SRType_ROR && imm5 == 0)
2469 shift_type = SRType_RRX;
2470
Johnny Chen82f16aa2011-02-15 20:10:55 +00002471 // Get the first operand.
2472 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2473 if (!success)
2474 return false;
2475
Johnny Cheneeab4852011-02-16 22:14:44 +00002476 // Decode the shift amount if not RRX.
2477 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002478
Johnny Chene97c0d52011-02-18 19:32:20 +00002479 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002480
2481 // The context specifies that an immediate is to be moved into Rd.
2482 EmulateInstruction::Context context;
2483 context.type = EmulateInstruction::eContextImmediate;
2484 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002485
Johnny Chen10530c22011-02-17 22:37:12 +00002486 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002487 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002488 }
2489 return true;
2490}
2491
Johnny Chene7f89532011-02-15 23:22:46 +00002492bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002493EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002494{
Johnny Chen41a0a152011-02-16 01:27:54 +00002495 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002496
2497 bool success = false;
2498 const uint32_t opcode = OpcodeAsUnsigned (&success);
2499 if (!success)
2500 return false;
2501
2502 if (ConditionPassed())
2503 {
2504 uint32_t Rd; // the destination register
2505 uint32_t Rn; // the first operand register
2506 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2507 uint32_t carry; // the carry bit after the shift operation
2508 bool setflags;
2509 switch (encoding) {
2510 case eEncodingT1:
2511 Rd = Bits32(opcode, 2, 0);
2512 Rn = Rd;
2513 Rm = Bits32(opcode, 5, 3);
2514 setflags = !InITBlock();
2515 break;
2516 case eEncodingT2:
2517 Rd = Bits32(opcode, 11, 8);
2518 Rn = Bits32(opcode, 19, 16);
2519 Rm = Bits32(opcode, 3, 0);
2520 setflags = BitIsSet(opcode, 20);
2521 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2522 return false;
2523 break;
2524 case eEncodingA1:
2525 Rd = Bits32(opcode, 15, 12);
2526 Rn = Bits32(opcode, 3, 0);
2527 Rm = Bits32(opcode, 11, 8);
2528 setflags = BitIsSet(opcode, 20);
2529 if (Rd == 15 || Rn == 15 || Rm == 15)
2530 return false;
2531 break;
2532 default:
2533 return false;
2534 }
2535
2536 // Get the first operand.
2537 uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
2538 if (!success)
2539 return false;
2540 // Get the Rm register content.
2541 uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
2542 if (!success)
2543 return false;
2544
2545 // Get the shift amount.
2546 uint32_t amt = Bits32(val, 7, 0);
2547
Johnny Chene97c0d52011-02-18 19:32:20 +00002548 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002549
2550 // The context specifies that an immediate is to be moved into Rd.
2551 EmulateInstruction::Context context;
2552 context.type = EmulateInstruction::eContextImmediate;
2553 context.SetNoArgs ();
2554
Johnny Chen10530c22011-02-17 22:37:12 +00002555 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002556 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002557 }
2558 return true;
2559}
2560
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002561// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002562// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002563// can be written back to the base register.
2564bool
2565EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2566{
2567#if 0
2568 // ARM pseudo code...
2569 if ConditionPassed()
2570 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2571 address = R[n];
2572
2573 for i = 0 to 14
2574 if registers<i> == '1' then
2575 R[i] = MemA[address, 4]; address = address + 4;
2576 if registers<15> == '1' then
2577 LoadWritePC (MemA[address, 4]);
2578
2579 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2580 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2581
2582#endif
2583
2584 bool success = false;
2585 const uint32_t opcode = OpcodeAsUnsigned (&success);
2586 if (!success)
2587 return false;
2588
2589 if (ConditionPassed())
2590 {
2591 uint32_t n;
2592 uint32_t registers = 0;
2593 bool wback;
2594 const uint32_t addr_byte_size = GetAddressByteSize();
2595 switch (encoding)
2596 {
2597 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002598 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002599 n = Bits32 (opcode, 10, 8);
2600 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002601 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002602 wback = BitIsClear (registers, n);
2603 // if BitCount(registers) < 1 then UNPREDICTABLE;
2604 if (BitCount(registers) < 1)
2605 return false;
2606 break;
2607 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002608 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2609 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002610 n = Bits32 (opcode, 19, 16);
2611 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002612 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002613 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002614
2615 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002616 if ((n == 15)
2617 || (BitCount (registers) < 2)
2618 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2619 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002620
2621 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002622 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002623 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002624
2625 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002626 if (wback
2627 && BitIsSet (registers, n))
2628 return false;
2629 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002630
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002631 case eEncodingA1:
2632 n = Bits32 (opcode, 19, 16);
2633 registers = Bits32 (opcode, 15, 0);
2634 wback = BitIsSet (opcode, 21);
2635 if ((n == 15)
2636 || (BitCount (registers) < 1))
2637 return false;
2638 break;
2639 default:
2640 return false;
2641 }
2642
2643 int32_t offset = 0;
2644 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2645 if (!success)
2646 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002647
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002648 EmulateInstruction::Context context;
2649 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2650 Register dwarf_reg;
2651 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2652 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002653
2654 for (int i = 0; i < 14; ++i)
2655 {
2656 if (BitIsSet (registers, i))
2657 {
Caroline Tice85aab332011-02-08 23:56:10 +00002658 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002659 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002660 if (wback && (n == 13)) // Pop Instruction
2661 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2662
2663 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002664 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002665 if (!success)
2666 return false;
2667
2668 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2669 return false;
2670
2671 offset += addr_byte_size;
2672 }
2673 }
2674
2675 if (BitIsSet (registers, 15))
2676 {
2677 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00002678 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002679 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002680 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002681 if (!success)
2682 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002683 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002684 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002685 return false;
2686 }
2687
2688 if (wback && BitIsClear (registers, n))
2689 {
Caroline Ticefa172202011-02-11 22:49:54 +00002690 // R[n] = R[n] + 4 * BitCount (registers)
2691 int32_t offset = addr_byte_size * BitCount (registers);
2692 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002693 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002694
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002695 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
2696 return false;
2697 }
2698 if (wback && BitIsSet (registers, n))
2699 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00002700 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002701 }
2702 return true;
2703}
Caroline Tice713c2662011-02-11 17:59:55 +00002704
2705// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
2706// The consecutive memorty locations end at this address and the address just below the lowest of those locations
2707// can optionally be written back tot he base registers.
2708bool
2709EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
2710{
2711#if 0
2712 // ARM pseudo code...
2713 if ConditionPassed() then
2714 EncodingSpecificOperations();
2715 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002716
Caroline Tice713c2662011-02-11 17:59:55 +00002717 for i = 0 to 14
2718 if registers<i> == ’1’ then
2719 R[i] = MemA[address,4]; address = address + 4;
2720
2721 if registers<15> == ’1’ then
2722 LoadWritePC(MemA[address,4]);
2723
2724 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2725 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2726#endif
2727
2728 bool success = false;
2729 const uint32_t opcode = OpcodeAsUnsigned (&success);
2730 if (!success)
2731 return false;
2732
2733 if (ConditionPassed())
2734 {
2735 uint32_t n;
2736 uint32_t registers = 0;
2737 bool wback;
2738 const uint32_t addr_byte_size = GetAddressByteSize();
2739
2740 // EncodingSpecificOperations();
2741 switch (encoding)
2742 {
2743 case eEncodingA1:
2744 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2745 n = Bits32 (opcode, 19, 16);
2746 registers = Bits32 (opcode, 15, 0);
2747 wback = BitIsSet (opcode, 21);
2748
2749 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2750 if ((n == 15) || (BitCount (registers) < 1))
2751 return false;
2752
2753 break;
2754
2755 default:
2756 return false;
2757 }
2758 // address = R[n] - 4*BitCount(registers) + 4;
2759
2760 int32_t offset = 0;
2761 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2762
2763 if (!success)
2764 return false;
2765
2766 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
2767
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002768 EmulateInstruction::Context context;
2769 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2770 Register dwarf_reg;
2771 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2772 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00002773
2774 // for i = 0 to 14
2775 for (int i = 0; i < 14; ++i)
2776 {
2777 // if registers<i> == ’1’ then
2778 if (BitIsSet (registers, i))
2779 {
2780 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002781 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002782 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002783 if (!success)
2784 return false;
2785 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2786 return false;
2787 offset += addr_byte_size;
2788 }
2789 }
2790
2791 // if registers<15> == ’1’ then
2792 // LoadWritePC(MemA[address,4]);
2793 if (BitIsSet (registers, 15))
2794 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002795 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002796 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00002797 if (!success)
2798 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00002799 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002800 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00002801 return false;
2802 }
2803
2804 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2805 if (wback && BitIsClear (registers, n))
2806 {
Caroline Tice713c2662011-02-11 17:59:55 +00002807 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2808 if (!success)
2809 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002810
2811 offset = (addr_byte_size * BitCount (registers)) * -1;
2812 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002813 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002814 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00002815 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2816 return false;
2817 }
2818
2819 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2820 if (wback && BitIsSet (registers, n))
2821 return WriteBits32Unknown (n);
2822 }
2823 return true;
2824}
2825
2826// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
2827// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
2828// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00002829bool
2830EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
2831{
2832#if 0
2833 // ARM pseudo code...
2834 if ConditionPassed() then
2835 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2836 address = R[n] - 4*BitCount(registers);
2837
2838 for i = 0 to 14
2839 if registers<i> == ’1’ then
2840 R[i] = MemA[address,4]; address = address + 4;
2841 if registers<15> == ’1’ then
2842 LoadWritePC(MemA[address,4]);
2843
2844 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2845 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2846#endif
2847
2848 bool success = false;
2849 const uint32_t opcode = OpcodeAsUnsigned (&success);
2850 if (!success)
2851 return false;
2852
2853 if (ConditionPassed())
2854 {
2855 uint32_t n;
2856 uint32_t registers = 0;
2857 bool wback;
2858 const uint32_t addr_byte_size = GetAddressByteSize();
2859 switch (encoding)
2860 {
2861 case eEncodingT1:
2862 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
2863 n = Bits32 (opcode, 19, 16);
2864 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002865 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00002866 wback = BitIsSet (opcode, 21);
2867
2868 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
2869 if ((n == 15)
2870 || (BitCount (registers) < 2)
2871 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2872 return false;
2873
2874 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002875 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00002876 return false;
2877
2878 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
2879 if (wback && BitIsSet (registers, n))
2880 return false;
2881
2882 break;
2883
2884 case eEncodingA1:
2885 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
2886 n = Bits32 (opcode, 19, 16);
2887 registers = Bits32 (opcode, 15, 0);
2888 wback = BitIsSet (opcode, 21);
2889
2890 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
2891 if ((n == 15) || (BitCount (registers) < 1))
2892 return false;
2893
2894 break;
2895
2896 default:
2897 return false;
2898 }
2899
Caroline Tice713c2662011-02-11 17:59:55 +00002900 // address = R[n] - 4*BitCount(registers);
2901
Caroline Tice0b29e242011-02-08 23:16:02 +00002902 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00002903 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2904
2905 if (!success)
2906 return false;
2907
2908 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002909 EmulateInstruction::Context context;
2910 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2911 Register dwarf_reg;
2912 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2913 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00002914
2915 for (int i = 0; i < 14; ++i)
2916 {
2917 if (BitIsSet (registers, i))
2918 {
2919 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002920 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002921 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002922 if (!success)
2923 return false;
2924
2925 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
2926 return false;
2927
2928 offset += addr_byte_size;
2929 }
2930 }
2931
2932 // if registers<15> == ’1’ then
2933 // LoadWritePC(MemA[address,4]);
2934 if (BitIsSet (registers, 15))
2935 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002936 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002937 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00002938 if (!success)
2939 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00002940 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00002941 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00002942 return false;
2943 }
2944
2945 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
2946 if (wback && BitIsClear (registers, n))
2947 {
Caroline Tice0b29e242011-02-08 23:16:02 +00002948 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2949 if (!success)
2950 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00002951
2952 offset = (addr_byte_size * BitCount (registers)) * -1;
2953 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002954 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00002955 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00002956 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
2957 return false;
2958 }
2959
2960 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2961 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00002962 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00002963 }
2964 return true;
2965}
Caroline Tice85aab332011-02-08 23:56:10 +00002966
Caroline Tice713c2662011-02-11 17:59:55 +00002967// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
2968// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
2969// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00002970bool
2971EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
2972{
2973#if 0
2974 if ConditionPassed() then
2975 EncodingSpecificOperations();
2976 address = R[n] + 4;
2977
2978 for i = 0 to 14
2979 if registers<i> == ’1’ then
2980 R[i] = MemA[address,4]; address = address + 4;
2981 if registers<15> == ’1’ then
2982 LoadWritePC(MemA[address,4]);
2983
2984 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
2985 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
2986#endif
2987
2988 bool success = false;
2989 const uint32_t opcode = OpcodeAsUnsigned (&success);
2990 if (!success)
2991 return false;
2992
2993 if (ConditionPassed())
2994 {
2995 uint32_t n;
2996 uint32_t registers = 0;
2997 bool wback;
2998 const uint32_t addr_byte_size = GetAddressByteSize();
2999 switch (encoding)
3000 {
3001 case eEncodingA1:
3002 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3003 n = Bits32 (opcode, 19, 16);
3004 registers = Bits32 (opcode, 15, 0);
3005 wback = BitIsSet (opcode, 21);
3006
3007 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3008 if ((n == 15) || (BitCount (registers) < 1))
3009 return false;
3010
3011 break;
3012 default:
3013 return false;
3014 }
3015 // address = R[n] + 4;
3016
3017 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003018 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3019
3020 if (!success)
3021 return false;
3022
3023 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003024
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003025 EmulateInstruction::Context context;
3026 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3027 Register dwarf_reg;
3028 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3029 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003030
3031 for (int i = 0; i < 14; ++i)
3032 {
3033 if (BitIsSet (registers, i))
3034 {
3035 // R[i] = MemA[address,4]; address = address + 4;
3036
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003037 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003038 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003039 if (!success)
3040 return false;
3041
3042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3043 return false;
3044
3045 offset += addr_byte_size;
3046 }
3047 }
3048
3049 // if registers<15> == ’1’ then
3050 // LoadWritePC(MemA[address,4]);
3051 if (BitIsSet (registers, 15))
3052 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003053 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003054 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003055 if (!success)
3056 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003057 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003058 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003059 return false;
3060 }
3061
3062 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3063 if (wback && BitIsClear (registers, n))
3064 {
Caroline Tice85aab332011-02-08 23:56:10 +00003065 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3066 if (!success)
3067 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003068
3069 offset = addr_byte_size * BitCount (registers);
3070 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003071 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003072 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3074 return false;
3075 }
3076
3077 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3078 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003079 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003080 }
3081 return true;
3082}
Caroline Tice0b29e242011-02-08 23:16:02 +00003083
Johnny Chenef21b592011-02-10 01:52:38 +00003084// Load Register (immediate) calculates an address from a base register value and
3085// an immediate offset, loads a word from memory, and writes to a register.
3086// LDR (immediate, Thumb)
3087bool
3088EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3089{
3090#if 0
3091 // ARM pseudo code...
3092 if (ConditionPassed())
3093 {
3094 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3095 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3096 address = if index then offset_addr else R[n];
3097 data = MemU[address,4];
3098 if wback then R[n] = offset_addr;
3099 if t == 15 then
3100 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3101 elsif UnalignedSupport() || address<1:0> = '00' then
3102 R[t] = data;
3103 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3104 }
3105#endif
3106
3107 bool success = false;
3108 const uint32_t opcode = OpcodeAsUnsigned (&success);
3109 if (!success)
3110 return false;
3111
3112 if (ConditionPassed())
3113 {
3114 uint32_t Rt; // the destination register
3115 uint32_t Rn; // the base register
3116 uint32_t imm32; // the immediate offset used to form the address
3117 addr_t offset_addr; // the offset address
3118 addr_t address; // the calculated address
3119 uint32_t data; // the literal data value from memory load
3120 bool add, index, wback;
3121 switch (encoding) {
3122 case eEncodingT1:
3123 Rt = Bits32(opcode, 5, 3);
3124 Rn = Bits32(opcode, 2, 0);
3125 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3126 // index = TRUE; add = TRUE; wback = FALSE
3127 add = true;
3128 index = true;
3129 wback = false;
3130 break;
3131 default:
3132 return false;
3133 }
3134 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3135 if (!success)
3136 return false;
3137 if (add)
3138 offset_addr = base + imm32;
3139 else
3140 offset_addr = base - imm32;
3141
3142 address = (index ? offset_addr : base);
3143
3144 if (wback)
3145 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003146 EmulateInstruction::Context ctx;
3147 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3148 Register dwarf_reg;
3149 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3150 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3151
Johnny Chenef21b592011-02-10 01:52:38 +00003152 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3153 return false;
3154 }
3155
3156 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003157 EmulateInstruction::Context context;
3158 context.type = EmulateInstruction::eContextImmediate;
3159 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003160
3161 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003162 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003163 if (!success)
3164 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003165
3166 if (Rt == 15)
3167 {
3168 if (Bits32(address, 1, 0) == 0)
3169 {
Johnny Chen668b4512011-02-15 21:08:58 +00003170 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003171 return false;
3172 }
3173 else
3174 return false;
3175 }
3176 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3177 {
3178 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3179 return false;
3180 }
3181 else
3182 return false;
3183 }
3184 return true;
3185}
3186
Caroline Ticeaf556562011-02-15 18:42:15 +00003187// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3188// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3189// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003190bool
3191EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3192{
3193#if 0
3194 if ConditionPassed() then
3195 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3196 address = R[n];
3197
3198 for i = 0 to 14
3199 if registers<i> == ’1’ then
3200 if i == n && wback && i != LowestSetBit(registers) then
3201 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3202 else
3203 MemA[address,4] = R[i];
3204 address = address + 4;
3205
3206 if registers<15> == ’1’ then // Only possible for encoding A1
3207 MemA[address,4] = PCStoreValue();
3208 if wback then R[n] = R[n] + 4*BitCount(registers);
3209#endif
3210
3211 bool success = false;
3212 const uint32_t opcode = OpcodeAsUnsigned (&success);
3213 if (!success)
3214 return false;
3215
3216 if (ConditionPassed ())
3217 {
3218 uint32_t n;
3219 uint32_t registers = 0;
3220 bool wback;
3221 const uint32_t addr_byte_size = GetAddressByteSize();
3222
3223 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3224 switch (encoding)
3225 {
3226 case eEncodingT1:
3227 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3228 n = Bits32 (opcode, 10, 8);
3229 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003230 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003231 wback = true;
3232
3233 // if BitCount(registers) < 1 then UNPREDICTABLE;
3234 if (BitCount (registers) < 1)
3235 return false;
3236
3237 break;
3238
3239 case eEncodingT2:
3240 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3241 n = Bits32 (opcode, 19, 16);
3242 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003243 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003244 wback = BitIsSet (opcode, 21);
3245
3246 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3247 if ((n == 15) || (BitCount (registers) < 2))
3248 return false;
3249
3250 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3251 if (wback && BitIsSet (registers, n))
3252 return false;
3253
3254 break;
3255
3256 case eEncodingA1:
3257 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3258 n = Bits32 (opcode, 19, 16);
3259 registers = Bits32 (opcode, 15, 0);
3260 wback = BitIsSet (opcode, 21);
3261
3262 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3263 if ((n == 15) || (BitCount (registers) < 1))
3264 return false;
3265
3266 break;
3267
3268 default:
3269 return false;
3270 }
3271
3272 // address = R[n];
3273 int32_t offset = 0;
3274 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3275 if (!success)
3276 return false;
3277
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003278 EmulateInstruction::Context context;
3279 context.type = EmulateInstruction::eContextRegisterStore;
3280 Register base_reg;
3281 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003282
3283 // for i = 0 to 14
3284 for (int i = 0; i < 14; ++i)
3285 {
3286 int lowest_set_bit = 14;
3287 // if registers<i> == ’1’ then
3288 if (BitIsSet (registers, i))
3289 {
3290 if (i < lowest_set_bit)
3291 lowest_set_bit = i;
3292 // if i == n && wback && i != LowestSetBit(registers) then
3293 if ((i == n) && wback && (i != lowest_set_bit))
3294 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3295 WriteBits32UnknownToMemory (address + offset);
3296 else
3297 {
3298 // MemA[address,4] = R[i];
3299 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3300 if (!success)
3301 return false;
3302
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003303 Register data_reg;
3304 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3305 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003306 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003307 return false;
3308 }
3309
3310 // address = address + 4;
3311 offset += addr_byte_size;
3312 }
3313 }
3314
3315 // if registers<15> == ’1’ then // Only possible for encoding A1
3316 // MemA[address,4] = PCStoreValue();
3317 if (BitIsSet (registers, 15))
3318 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003319 Register pc_reg;
3320 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3321 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003322 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3323 if (!success)
3324 return false;
3325
Caroline Ticecc96eb52011-02-17 19:20:40 +00003326 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003327 return false;
3328 }
3329
3330 // if wback then R[n] = R[n] + 4*BitCount(registers);
3331 if (wback)
3332 {
3333 offset = addr_byte_size * BitCount (registers);
3334 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003335 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003336 addr_t data = address + offset;
3337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3338 return false;
3339 }
3340 }
3341 return true;
3342}
3343
Caroline Ticeaf556562011-02-15 18:42:15 +00003344// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3345// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3346// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003347bool
3348EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3349{
3350#if 0
3351 if ConditionPassed() then
3352 EncodingSpecificOperations();
3353 address = R[n] - 4*BitCount(registers) + 4;
3354
3355 for i = 0 to 14
3356 if registers<i> == ’1’ then
3357 if i == n && wback && i != LowestSetBit(registers) then
3358 MemA[address,4] = bits(32) UNKNOWN;
3359 else
3360 MemA[address,4] = R[i];
3361 address = address + 4;
3362
3363 if registers<15> == ’1’ then
3364 MemA[address,4] = PCStoreValue();
3365
3366 if wback then R[n] = R[n] - 4*BitCount(registers);
3367#endif
3368
3369 bool success = false;
3370 const uint32_t opcode = OpcodeAsUnsigned (&success);
3371 if (!success)
3372 return false;
3373
3374 if (ConditionPassed ())
3375 {
3376 uint32_t n;
3377 uint32_t registers = 0;
3378 bool wback;
3379 const uint32_t addr_byte_size = GetAddressByteSize();
3380
3381 // EncodingSpecificOperations();
3382 switch (encoding)
3383 {
3384 case eEncodingA1:
3385 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3386 n = Bits32 (opcode, 19, 16);
3387 registers = Bits32 (opcode, 15, 0);
3388 wback = BitIsSet (opcode, 21);
3389
3390 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3391 if ((n == 15) || (BitCount (registers) < 1))
3392 return false;
3393 break;
3394 default:
3395 return false;
3396 }
3397
3398 // address = R[n] - 4*BitCount(registers) + 4;
3399 int32_t offset = 0;
3400 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3401 if (!success)
3402 return false;
3403
3404 address = address - (addr_byte_size * BitCount (registers)) + 4;
3405
3406 EmulateInstruction::Context context;
3407 context.type = EmulateInstruction::eContextRegisterStore;
3408 Register base_reg;
3409 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3410
3411 // for i = 0 to 14
3412 for (int i = 0; i < 14; ++i)
3413 {
3414 int lowest_bit_set = 14;
3415 // if registers<i> == ’1’ then
3416 if (BitIsSet (registers, i))
3417 {
3418 if (i < lowest_bit_set)
3419 lowest_bit_set = i;
3420 //if i == n && wback && i != LowestSetBit(registers) then
3421 if ((i == n) && wback && (i != lowest_bit_set))
3422 // MemA[address,4] = bits(32) UNKNOWN;
3423 WriteBits32UnknownToMemory (address + offset);
3424 else
3425 {
3426 // MemA[address,4] = R[i];
3427 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3428 if (!success)
3429 return false;
3430
3431 Register data_reg;
3432 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3433 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003434 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003435 return false;
3436 }
3437
3438 // address = address + 4;
3439 offset += addr_byte_size;
3440 }
3441 }
3442
3443 // if registers<15> == ’1’ then
3444 // MemA[address,4] = PCStoreValue();
3445 if (BitIsSet (registers, 15))
3446 {
3447 Register pc_reg;
3448 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3449 context.SetRegisterPlusOffset (pc_reg, 8);
3450 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3451 if (!success)
3452 return false;
3453
Caroline Ticecc96eb52011-02-17 19:20:40 +00003454 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003455 return false;
3456 }
3457
3458 // if wback then R[n] = R[n] - 4*BitCount(registers);
3459 if (wback)
3460 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003461 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003462 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3463 context.SetImmediateSigned (offset);
3464 addr_t data = address + offset;
3465 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3466 return false;
3467 }
3468 }
3469 return true;
3470}
3471
Caroline Ticeaf556562011-02-15 18:42:15 +00003472// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3473// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3474// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003475bool
3476EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3477{
3478#if 0
3479 if ConditionPassed() then
3480 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3481 address = R[n] - 4*BitCount(registers);
3482
3483 for i = 0 to 14
3484 if registers<i> == ’1’ then
3485 if i == n && wback && i != LowestSetBit(registers) then
3486 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3487 else
3488 MemA[address,4] = R[i];
3489 address = address + 4;
3490
3491 if registers<15> == ’1’ then // Only possible for encoding A1
3492 MemA[address,4] = PCStoreValue();
3493
3494 if wback then R[n] = R[n] - 4*BitCount(registers);
3495#endif
3496
3497
3498 bool success = false;
3499 const uint32_t opcode = OpcodeAsUnsigned (&success);
3500 if (!success)
3501 return false;
3502
3503 if (ConditionPassed ())
3504 {
3505 uint32_t n;
3506 uint32_t registers = 0;
3507 bool wback;
3508 const uint32_t addr_byte_size = GetAddressByteSize();
3509
3510 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3511 switch (encoding)
3512 {
3513 case eEncodingT1:
3514 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3515 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3516 {
3517 // See PUSH
3518 }
3519 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3520 n = Bits32 (opcode, 19, 16);
3521 registers = Bits32 (opcode, 15, 0);
3522 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3523 wback = BitIsSet (opcode, 21);
3524 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3525 if ((n == 15) || BitCount (registers) < 2)
3526 return false;
3527 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3528 if (wback && BitIsSet (registers, n))
3529 return false;
3530 break;
3531
3532 case eEncodingA1:
3533 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3534 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3535 {
3536 // See Push
3537 }
3538 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3539 n = Bits32 (opcode, 19, 16);
3540 registers = Bits32 (opcode, 15, 0);
3541 wback = BitIsSet (opcode, 21);
3542 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3543 if ((n == 15) || BitCount (registers) < 1)
3544 return false;
3545 break;
3546
3547 default:
3548 return false;
3549 }
3550
3551 // address = R[n] - 4*BitCount(registers);
3552
3553 int32_t offset = 0;
3554 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3555 if (!success)
3556 return false;
3557
3558 address = address - (addr_byte_size * BitCount (registers));
3559
3560 EmulateInstruction::Context context;
3561 context.type = EmulateInstruction::eContextRegisterStore;
3562 Register base_reg;
3563 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3564
3565 // for i = 0 to 14
3566 for (int i = 0; i < 14; ++i)
3567 {
3568 uint32_t lowest_set_bit = 14;
3569 // if registers<i> == ’1’ then
3570 if (BitIsSet (registers, i))
3571 {
3572 if (i < lowest_set_bit)
3573 lowest_set_bit = i;
3574 // if i == n && wback && i != LowestSetBit(registers) then
3575 if ((i == n) && wback && (i != lowest_set_bit))
3576 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3577 WriteBits32UnknownToMemory (address + offset);
3578 else
3579 {
3580 // MemA[address,4] = R[i];
3581 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3582 if (!success)
3583 return false;
3584
3585 Register data_reg;
3586 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3587 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003588 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003589 return false;
3590 }
3591
3592 // address = address + 4;
3593 offset += addr_byte_size;
3594 }
3595 }
3596
3597 // if registers<15> == ’1’ then // Only possible for encoding A1
3598 // MemA[address,4] = PCStoreValue();
3599 if (BitIsSet (registers, 15))
3600 {
3601 Register pc_reg;
3602 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3603 context.SetRegisterPlusOffset (pc_reg, 8);
3604 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3605 if (!success)
3606 return false;
3607
Caroline Ticecc96eb52011-02-17 19:20:40 +00003608 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003609 return false;
3610 }
3611
3612 // if wback then R[n] = R[n] - 4*BitCount(registers);
3613 if (wback)
3614 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003615 offset = (addr_byte_size * BitCount (registers)) * -1;
3616 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3617 context.SetImmediateSigned (offset);
3618 addr_t data = address + offset;
3619 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3620 return false;
3621 }
3622 }
3623 return true;
3624}
3625
3626// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3627// from a base register. The consecutive memory locations start just above this address, and the address of the last
3628// of those locations can optionally be written back to the base register.
3629bool
3630EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3631{
3632#if 0
3633 if ConditionPassed() then
3634 EncodingSpecificOperations();
3635 address = R[n] + 4;
3636
3637 for i = 0 to 14
3638 if registers<i> == ’1’ then
3639 if i == n && wback && i != LowestSetBit(registers) then
3640 MemA[address,4] = bits(32) UNKNOWN;
3641 else
3642 MemA[address,4] = R[i];
3643 address = address + 4;
3644
3645 if registers<15> == ’1’ then
3646 MemA[address,4] = PCStoreValue();
3647
3648 if wback then R[n] = R[n] + 4*BitCount(registers);
3649#endif
3650
3651 bool success = false;
3652 const uint32_t opcode = OpcodeAsUnsigned (&success);
3653 if (!success)
3654 return false;
3655
3656 if (ConditionPassed())
3657 {
3658 uint32_t n;
3659 uint32_t registers = 0;
3660 bool wback;
3661 const uint32_t addr_byte_size = GetAddressByteSize();
3662
3663 // EncodingSpecificOperations();
3664 switch (encoding)
3665 {
3666 case eEncodingA1:
3667 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3668 n = Bits32 (opcode, 19, 16);
3669 registers = Bits32 (opcode, 15, 0);
3670 wback = BitIsSet (opcode, 21);
3671
3672 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3673 if ((n == 15) && (BitCount (registers) < 1))
3674 return false;
3675 break;
3676 default:
3677 return false;
3678 }
3679 // address = R[n] + 4;
3680
3681 int32_t offset = 0;
3682 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3683 if (!success)
3684 return false;
3685
3686 address = address + addr_byte_size;
3687
3688 EmulateInstruction::Context context;
3689 context.type = EmulateInstruction::eContextRegisterStore;
3690 Register base_reg;
3691 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3692
3693 uint32_t lowest_set_bit = 14;
3694 // for i = 0 to 14
3695 for (int i = 0; i < 14; ++i)
3696 {
3697 // if registers<i> == ’1’ then
3698 if (BitIsSet (registers, i))
3699 {
3700 if (i < lowest_set_bit)
3701 lowest_set_bit = i;
3702 // if i == n && wback && i != LowestSetBit(registers) then
3703 if ((i == n) && wback && (i != lowest_set_bit))
3704 // MemA[address,4] = bits(32) UNKNOWN;
3705 WriteBits32UnknownToMemory (address + offset);
3706 // else
3707 else
3708 {
3709 // MemA[address,4] = R[i];
3710 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3711 if (!success)
3712 return false;
3713
3714 Register data_reg;
3715 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3716 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003717 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003718 return false;
3719 }
3720
3721 // address = address + 4;
3722 offset += addr_byte_size;
3723 }
3724 }
3725
3726 // if registers<15> == ’1’ then
3727 // MemA[address,4] = PCStoreValue();
3728 if (BitIsSet (registers, 15))
3729 {
3730 Register pc_reg;
3731 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3732 context.SetRegisterPlusOffset (pc_reg, 8);
3733 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3734 if (!success)
3735 return false;
3736
Caroline Ticecc96eb52011-02-17 19:20:40 +00003737 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00003738 return false;
3739 }
3740
3741 // if wback then R[n] = R[n] + 4*BitCount(registers);
3742 if (wback)
3743 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003744 offset = addr_byte_size * BitCount (registers);
3745 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3746 context.SetImmediateSigned (offset);
3747 addr_t data = address + offset;
3748 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3749 return false;
3750 }
3751 }
3752 return true;
3753}
Caroline Tice7fac8572011-02-15 22:53:54 +00003754
3755// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
3756// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
3757bool
3758EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
3759{
3760#if 0
3761 if ConditionPassed() then
3762 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3763 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3764 address = if index then offset_addr else R[n];
3765 if UnalignedSupport() || address<1:0> == ’00’ then
3766 MemU[address,4] = R[t];
3767 else // Can only occur before ARMv7
3768 MemU[address,4] = bits(32) UNKNOWN;
3769 if wback then R[n] = offset_addr;
3770#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003771
Caroline Tice7fac8572011-02-15 22:53:54 +00003772 bool success = false;
3773 const uint32_t opcode = OpcodeAsUnsigned (&success);
3774 if (!success)
3775 return false;
3776
3777 if (ConditionPassed())
3778 {
3779 const uint32_t addr_byte_size = GetAddressByteSize();
3780
3781 uint32_t t;
3782 uint32_t n;
3783 uint32_t imm32;
3784 bool index;
3785 bool add;
3786 bool wback;
3787 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3788 switch (encoding)
3789 {
3790 case eEncodingT1:
3791 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
3792 t = Bits32 (opcode, 2, 0);
3793 n = Bits32 (opcode, 5, 3);
3794 imm32 = Bits32 (opcode, 10, 6) << 2;
3795
3796 // index = TRUE; add = TRUE; wback = FALSE;
3797 index = true;
3798 add = false;
3799 wback = false;
3800 break;
3801
3802 case eEncodingT2:
3803 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
3804 t = Bits32 (opcode, 10, 8);
3805 n = 13;
3806 imm32 = Bits32 (opcode, 7, 0) << 2;
3807
3808 // index = TRUE; add = TRUE; wback = FALSE;
3809 index = true;
3810 add = true;
3811 wback = false;
3812 break;
3813
3814 case eEncodingT3:
3815 // if Rn == ’1111’ then UNDEFINED;
3816 if (Bits32 (opcode, 19, 16) == 15)
3817 return false;
3818
3819 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3820 t = Bits32 (opcode, 15, 12);
3821 n = Bits32 (opcode, 19, 16);
3822 imm32 = Bits32 (opcode, 11, 0);
3823
3824 // index = TRUE; add = TRUE; wback = FALSE;
3825 index = true;
3826 add = true;
3827 wback = false;
3828
3829 // if t == 15 then UNPREDICTABLE;
3830 if (t == 15)
3831 return false;
3832 break;
3833
3834 case eEncodingT4:
3835 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
3836 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
3837 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
3838 if ((Bits32 (opcode, 19, 16) == 15)
3839 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
3840 return false;
3841
3842 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3843 t = Bits32 (opcode, 15, 12);
3844 n = Bits32 (opcode, 19, 16);
3845 imm32 = Bits32 (opcode, 7, 0);
3846
3847 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
3848 index = BitIsSet (opcode, 10);
3849 add = BitIsSet (opcode, 9);
3850 wback = BitIsSet (opcode, 8);
3851
3852 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
3853 if ((t == 15) || (wback && (n == t)))
3854 return false;
3855 break;
3856
3857 default:
3858 return false;
3859 }
3860
3861 addr_t offset_addr;
3862 addr_t address;
3863
3864 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3865 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3866 if (!success)
3867 return false;
3868
3869 if (add)
3870 offset_addr = base_address + imm32;
3871 else
3872 offset_addr = base_address - imm32;
3873
3874 // address = if index then offset_addr else R[n];
3875 if (index)
3876 address = offset_addr;
3877 else
3878 address = base_address;
3879
3880 EmulateInstruction::Context context;
3881 context.type = eContextRegisterStore;
3882 Register base_reg;
3883 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3884
3885 // if UnalignedSupport() || address<1:0> == ’00’ then
3886 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
3887 {
3888 // MemU[address,4] = R[t];
3889 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
3890 if (!success)
3891 return false;
3892
3893 Register data_reg;
3894 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
3895 int32_t offset = address - base_address;
3896 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003897 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00003898 return false;
3899 }
3900 else
3901 {
3902 // MemU[address,4] = bits(32) UNKNOWN;
3903 WriteBits32UnknownToMemory (address);
3904 }
3905
3906 // if wback then R[n] = offset_addr;
3907 if (wback)
3908 {
3909 context.type = eContextRegisterLoad;
3910 context.SetAddress (offset_addr);
3911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
3912 return false;
3913 }
3914 }
3915 return true;
3916}
Caroline Ticeaf556562011-02-15 18:42:15 +00003917
Caroline Tice3fd63e92011-02-16 00:33:43 +00003918// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
3919// word from a register to memory. The offset register value can optionally be shifted.
3920bool
3921EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
3922{
3923#if 0
3924 if ConditionPassed() then
3925 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3926 offset = Shift(R[m], shift_t, shift_n, APSR.C);
3927 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
3928 address = if index then offset_addr else R[n];
3929 if t == 15 then // Only possible for encoding A1
3930 data = PCStoreValue();
3931 else
3932 data = R[t];
3933 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
3934 MemU[address,4] = data;
3935 else // Can only occur before ARMv7
3936 MemU[address,4] = bits(32) UNKNOWN;
3937 if wback then R[n] = offset_addr;
3938#endif
3939
3940 bool success = false;
3941 const uint32_t opcode = OpcodeAsUnsigned (&success);
3942 if (!success)
3943 return false;
3944
3945 if (ConditionPassed())
3946 {
3947 const uint32_t addr_byte_size = GetAddressByteSize();
3948
3949 uint32_t t;
3950 uint32_t n;
3951 uint32_t m;
3952 ARM_ShifterType shift_t;
3953 uint32_t shift_n;
3954 bool index;
3955 bool add;
3956 bool wback;
3957
3958 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
3959 switch (encoding)
3960 {
3961 case eEncodingT1:
3962 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
3963 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3964 t = Bits32 (opcode, 2, 0);
3965 n = Bits32 (opcode, 5, 3);
3966 m = Bits32 (opcode, 8, 6);
3967
3968 // index = TRUE; add = TRUE; wback = FALSE;
3969 index = true;
3970 add = true;
3971 wback = false;
3972
3973 // (shift_t, shift_n) = (SRType_LSL, 0);
3974 shift_t = SRType_LSL;
3975 shift_n = 0;
3976 break;
3977
3978 case eEncodingT2:
3979 // if Rn == ’1111’ then UNDEFINED;
3980 if (Bits32 (opcode, 19, 16) == 15)
3981 return false;
3982
3983 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
3984 t = Bits32 (opcode, 15, 12);
3985 n = Bits32 (opcode, 19, 16);
3986 m = Bits32 (opcode, 3, 0);
3987
3988 // index = TRUE; add = TRUE; wback = FALSE;
3989 index = true;
3990 add = true;
3991 wback = false;
3992
3993 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
3994 shift_t = SRType_LSL;
3995 shift_n = Bits32 (opcode, 5, 4);
3996
3997 // if t == 15 || BadReg(m) then UNPREDICTABLE;
3998 if ((t == 15) || (BadReg (m)))
3999 return false;
4000 break;
4001
4002 case eEncodingA1:
4003 {
4004 // if P == ’0’ && W == ’1’ then SEE STRT;
4005 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4006 t = Bits32 (opcode, 15, 12);
4007 n = Bits32 (opcode, 19, 16);
4008 m = Bits32 (opcode, 3, 0);
4009
4010 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4011 index = BitIsSet (opcode, 24);
4012 add = BitIsSet (opcode, 23);
4013 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4014
4015 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4016 uint32_t typ = Bits32 (opcode, 6, 5);
4017 uint32_t imm5 = Bits32 (opcode, 11, 7);
4018 shift_n = DecodeImmShift(typ, imm5, shift_t);
4019
4020 // if m == 15 then UNPREDICTABLE;
4021 if (m == 15)
4022 return false;
4023
4024 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4025 if (wback && ((n == 15) || (n == t)))
4026 return false;
4027
4028 break;
4029 }
4030 default:
4031 return false;
4032 }
4033
4034 addr_t offset_addr;
4035 addr_t address;
4036 int32_t offset = 0;
4037
4038 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4039 if (!success)
4040 return false;
4041
4042 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4043 if (!success)
4044 return false;
4045
4046 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004047 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004048
4049 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4050 if (add)
4051 offset_addr = base_address + offset;
4052 else
4053 offset_addr = base_address - offset;
4054
4055 // address = if index then offset_addr else R[n];
4056 if (index)
4057 address = offset_addr;
4058 else
4059 address = base_address;
4060
4061 uint32_t data;
4062 // if t == 15 then // Only possible for encoding A1
4063 if (t == 15)
4064 // data = PCStoreValue();
4065 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4066 else
4067 // data = R[t];
4068 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4069
4070 if (!success)
4071 return false;
4072
4073 EmulateInstruction::Context context;
4074 context.type = eContextRegisterStore;
4075
4076 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4077 if (UnalignedSupport ()
4078 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4079 || CurrentInstrSet() == eModeARM)
4080 {
4081 // MemU[address,4] = data;
4082
4083 Register base_reg;
4084 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4085
4086 Register data_reg;
4087 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4088
4089 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004090 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004091 return false;
4092
4093 }
4094 else
4095 // MemU[address,4] = bits(32) UNKNOWN;
4096 WriteBits32UnknownToMemory (address);
4097
4098 // if wback then R[n] = offset_addr;
4099 if (wback)
4100 {
4101 context.type = eContextRegisterLoad;
4102 context.SetAddress (offset_addr);
4103 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4104 return false;
4105 }
4106
4107 }
4108 return true;
4109}
Caroline Tice73a29de2011-02-16 20:22:22 +00004110
4111bool
4112EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4113{
4114#if 0
4115 if ConditionPassed() then
4116 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4117 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4118 address = if index then offset_addr else R[n];
4119 MemU[address,1] = R[t]<7:0>;
4120 if wback then R[n] = offset_addr;
4121#endif
4122
4123
4124 bool success = false;
4125 const uint32_t opcode = OpcodeAsUnsigned (&success);
4126 if (!success)
4127 return false;
4128
4129 if (ConditionPassed ())
4130 {
4131 uint32_t t;
4132 uint32_t n;
4133 uint32_t imm32;
4134 bool index;
4135 bool add;
4136 bool wback;
4137 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4138 switch (encoding)
4139 {
4140 case eEncodingT1:
4141 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4142 t = Bits32 (opcode, 2, 0);
4143 n = Bits32 (opcode, 5, 3);
4144 imm32 = Bits32 (opcode, 10, 6);
4145
4146 // index = TRUE; add = TRUE; wback = FALSE;
4147 index = true;
4148 add = true;
4149 wback = false;
4150 break;
4151
4152 case eEncodingT2:
4153 // if Rn == ’1111’ then UNDEFINED;
4154 if (Bits32 (opcode, 19, 16) == 15)
4155 return false;
4156
4157 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4158 t = Bits32 (opcode, 15, 12);
4159 n = Bits32 (opcode, 19, 16);
4160 imm32 = Bits32 (opcode, 11, 0);
4161
4162 // index = TRUE; add = TRUE; wback = FALSE;
4163 index = true;
4164 add = true;
4165 wback = false;
4166
4167 // if BadReg(t) then UNPREDICTABLE;
4168 if (BadReg (t))
4169 return false;
4170 break;
4171
4172 case eEncodingT3:
4173 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4174 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4175 if (Bits32 (opcode, 19, 16) == 15)
4176 return false;
4177
4178 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4179 t = Bits32 (opcode, 15, 12);
4180 n = Bits32 (opcode, 19, 16);
4181 imm32 = Bits32 (opcode, 7, 0);
4182
4183 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4184 index = BitIsSet (opcode, 10);
4185 add = BitIsSet (opcode, 9);
4186 wback = BitIsSet (opcode, 8);
4187
4188 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4189 if ((BadReg (t)) || (wback && (n == t)))
4190 return false;
4191 break;
4192
4193 default:
4194 return false;
4195 }
4196
4197 addr_t offset_addr;
4198 addr_t address;
4199 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4200 if (!success)
4201 return false;
4202
4203 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4204 if (add)
4205 offset_addr = base_address + imm32;
4206 else
4207 offset_addr = base_address - imm32;
4208
4209 // address = if index then offset_addr else R[n];
4210 if (index)
4211 address = offset_addr;
4212 else
4213 address = base_address;
4214
Caroline Ticecc96eb52011-02-17 19:20:40 +00004215 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004216 Register base_reg;
4217 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4218
4219 Register data_reg;
4220 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4221
4222 EmulateInstruction::Context context;
4223 context.type = eContextRegisterStore;
4224 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4225
4226 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4227 if (!success)
4228 return false;
4229
4230 data = Bits32 (data, 7, 0);
4231
Caroline Ticecc96eb52011-02-17 19:20:40 +00004232 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004233 return false;
4234
4235 // if wback then R[n] = offset_addr;
4236 if (wback)
4237 {
4238 context.type = eContextRegisterLoad;
4239 context.SetAddress (offset_addr);
4240 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4241 return false;
4242 }
4243
4244 }
4245
4246 return true;
4247}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004248
Johnny Chen157b9592011-02-18 21:13:05 +00004249// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4250// and writes the result to the destination register. It can optionally update the condition flags
4251// based on the result.
4252bool
4253EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4254{
4255#if 0
4256 // ARM pseudo code...
4257 if ConditionPassed() then
4258 EncodingSpecificOperations();
4259 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4260 if d == 15 then // Can only occur for ARM encoding
4261 ALUWritePC(result); // setflags is always FALSE here
4262 else
4263 R[d] = result;
4264 if setflags then
4265 APSR.N = result<31>;
4266 APSR.Z = IsZeroBit(result);
4267 APSR.C = carry;
4268 APSR.V = overflow;
4269#endif
4270
4271 bool success = false;
4272 const uint32_t opcode = OpcodeAsUnsigned (&success);
4273 if (!success)
4274 return false;
4275
4276 if (ConditionPassed())
4277 {
4278 uint32_t Rd, Rn;
4279 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4280 bool setflags;
4281 switch (encoding)
4282 {
4283 case eEncodingT1:
4284 Rd = Bits32(opcode, 11, 8);
4285 Rn = Bits32(opcode, 19, 16);
4286 setflags = BitIsSet(opcode, 20);
4287 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4288 if (BadReg(Rd) || BadReg(Rn))
4289 return false;
4290 break;
4291 case eEncodingA1:
4292 Rd = Bits32(opcode, 15, 12);
4293 Rn = Bits32(opcode, 19, 16);
4294 setflags = BitIsSet(opcode, 20);
4295 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4296 // TODO: Emulate SUBS PC, LR and related instructions.
4297 if (Rd == 15 && setflags)
4298 return false;
4299 break;
4300 default:
4301 return false;
4302 }
4303
4304 // Read the first operand.
4305 int32_t val1 = ReadCoreReg(Rn, &success);
4306 if (!success)
4307 return false;
4308
4309 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4310
4311 EmulateInstruction::Context context;
4312 context.type = EmulateInstruction::eContextImmediate;
4313 context.SetNoArgs ();
4314
4315 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4316 return false;
4317 }
4318 return true;
4319}
4320
4321// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4322// register value, and writes the result to the destination register. It can optionally update the
4323// condition flags based on the result.
4324bool
4325EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4326{
4327#if 0
4328 // ARM pseudo code...
4329 if ConditionPassed() then
4330 EncodingSpecificOperations();
4331 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4332 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4333 if d == 15 then // Can only occur for ARM encoding
4334 ALUWritePC(result); // setflags is always FALSE here
4335 else
4336 R[d] = result;
4337 if setflags then
4338 APSR.N = result<31>;
4339 APSR.Z = IsZeroBit(result);
4340 APSR.C = carry;
4341 APSR.V = overflow;
4342#endif
4343
4344 bool success = false;
4345 const uint32_t opcode = OpcodeAsUnsigned (&success);
4346 if (!success)
4347 return false;
4348
4349 if (ConditionPassed())
4350 {
4351 uint32_t Rd, Rn, Rm;
4352 ARM_ShifterType shift_t;
4353 uint32_t shift_n; // the shift applied to the value read from Rm
4354 bool setflags;
4355 switch (encoding)
4356 {
4357 case eEncodingT1:
4358 Rd = Rn = Bits32(opcode, 2, 0);
4359 Rm = Bits32(opcode, 5, 3);
4360 setflags = !InITBlock();
4361 shift_t = SRType_LSL;
4362 shift_n = 0;
4363 case eEncodingT2:
4364 Rd = Bits32(opcode, 11, 8);
4365 Rn = Bits32(opcode, 19, 16);
4366 Rm = Bits32(opcode, 3, 0);
4367 setflags = BitIsSet(opcode, 20);
4368 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
4369 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4370 return false;
4371 break;
4372 case eEncodingA1:
4373 Rd = Bits32(opcode, 15, 12);
4374 Rn = Bits32(opcode, 19, 16);
4375 Rm = Bits32(opcode, 3, 0);
4376 setflags = BitIsSet(opcode, 20);
4377 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4378 // TODO: Emulate SUBS PC, LR and related instructions.
4379 if (Rd == 15 && setflags)
4380 return false;
4381 break;
4382 default:
4383 return false;
4384 }
4385
4386 // Read the first operand.
4387 int32_t val1 = ReadCoreReg(Rn, &success);
4388 if (!success)
4389 return false;
4390
4391 // Read the second operand.
4392 int32_t val2 = ReadCoreReg(Rm, &success);
4393 if (!success)
4394 return false;
4395
4396 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4397 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4398
4399 EmulateInstruction::Context context;
4400 context.type = EmulateInstruction::eContextImmediate;
4401 context.SetNoArgs ();
4402
4403 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4404 return false;
4405 }
4406 return true;
4407}
4408
Johnny Chene97c0d52011-02-18 19:32:20 +00004409// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4410// to the destination register. It can optionally update the condition flags based on the result.
4411bool
4412EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4413{
4414#if 0
4415 // ARM pseudo code...
4416 if ConditionPassed() then
4417 EncodingSpecificOperations();
4418 result = R[n] AND imm32;
4419 if d == 15 then // Can only occur for ARM encoding
4420 ALUWritePC(result); // setflags is always FALSE here
4421 else
4422 R[d] = result;
4423 if setflags then
4424 APSR.N = result<31>;
4425 APSR.Z = IsZeroBit(result);
4426 APSR.C = carry;
4427 // APSR.V unchanged
4428#endif
4429
4430 bool success = false;
4431 const uint32_t opcode = OpcodeAsUnsigned (&success);
4432 if (!success)
4433 return false;
4434
4435 if (ConditionPassed())
4436 {
4437 uint32_t Rd, Rn;
4438 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4439 bool setflags;
4440 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4441 switch (encoding)
4442 {
4443 case eEncodingT1:
4444 Rd = Bits32(opcode, 11, 8);
4445 Rn = Bits32(opcode, 19, 16);
4446 setflags = BitIsSet(opcode, 20);
4447 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
4448 // TODO: Emulate TST (immediate)
4449 if (Rd == 15 && setflags)
4450 return false;
4451 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4452 return false;
4453 break;
4454 case eEncodingA1:
4455 Rd = Bits32(opcode, 15, 12);
4456 Rn = Bits32(opcode, 19, 16);
4457 setflags = BitIsSet(opcode, 20);
4458 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4459 // TODO: Emulate SUBS PC, LR and related instructions.
4460 if (Rd == 15 && setflags)
4461 return false;
4462 break;
4463 default:
4464 return false;
4465 }
4466
Johnny Chene97c0d52011-02-18 19:32:20 +00004467 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004468 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004469 if (!success)
4470 return false;
4471
4472 uint32_t result = val1 & imm32;
4473
4474 EmulateInstruction::Context context;
4475 context.type = EmulateInstruction::eContextImmediate;
4476 context.SetNoArgs ();
4477
4478 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4479 return false;
4480 }
4481 return true;
4482}
4483
4484// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4485// and writes the result to the destination register. It can optionally update the condition flags
4486// based on the result.
4487bool
4488EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4489{
4490#if 0
4491 // ARM pseudo code...
4492 if ConditionPassed() then
4493 EncodingSpecificOperations();
4494 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4495 result = R[n] AND shifted;
4496 if d == 15 then // Can only occur for ARM encoding
4497 ALUWritePC(result); // setflags is always FALSE here
4498 else
4499 R[d] = result;
4500 if setflags then
4501 APSR.N = result<31>;
4502 APSR.Z = IsZeroBit(result);
4503 APSR.C = carry;
4504 // APSR.V unchanged
4505#endif
4506
4507 bool success = false;
4508 const uint32_t opcode = OpcodeAsUnsigned (&success);
4509 if (!success)
4510 return false;
4511
4512 if (ConditionPassed())
4513 {
4514 uint32_t Rd, Rn, Rm;
4515 ARM_ShifterType shift_t;
4516 uint32_t shift_n; // the shift applied to the value read from Rm
4517 bool setflags;
4518 uint32_t carry;
4519 switch (encoding)
4520 {
4521 case eEncodingT1:
4522 Rd = Rn = Bits32(opcode, 2, 0);
4523 Rm = Bits32(opcode, 5, 3);
4524 setflags = !InITBlock();
4525 shift_t = SRType_LSL;
4526 shift_n = 0;
4527 case eEncodingT2:
4528 Rd = Bits32(opcode, 11, 8);
4529 Rn = Bits32(opcode, 19, 16);
4530 Rm = Bits32(opcode, 3, 0);
4531 setflags = BitIsSet(opcode, 20);
Johnny Chen157b9592011-02-18 21:13:05 +00004532 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004533 // TODO: Emulate TST (register)
4534 if (Rd == 15 && setflags)
4535 return false;
4536 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4537 return false;
4538 break;
4539 case eEncodingA1:
4540 Rd = Bits32(opcode, 15, 12);
4541 Rn = Bits32(opcode, 19, 16);
4542 Rm = Bits32(opcode, 3, 0);
4543 setflags = BitIsSet(opcode, 20);
4544 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
4545 // TODO: Emulate SUBS PC, LR and related instructions.
4546 if (Rd == 15 && setflags)
4547 return false;
4548 break;
4549 default:
4550 return false;
4551 }
4552
Johnny Chene97c0d52011-02-18 19:32:20 +00004553 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004554 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004555 if (!success)
4556 return false;
4557
4558 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004559 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004560 if (!success)
4561 return false;
4562
4563 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4564 uint32_t result = val1 & shifted;
4565
4566 EmulateInstruction::Context context;
4567 context.type = EmulateInstruction::eContextImmediate;
4568 context.SetNoArgs ();
4569
4570 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4571 return false;
4572 }
4573 return true;
4574}
4575
Caroline Tice4d729c52011-02-18 00:55:53 +00004576// 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 +00004577// 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 +00004578bool
4579EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
4580{
4581#if 0
4582 if ConditionPassed() then
4583 EncodingSpecificOperations();
4584 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4585 address = if index then offset_addr else R[n];
4586 data = MemU[address,4];
4587 if wback then R[n] = offset_addr;
4588 if t == 15 then
4589 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4590 elsif UnalignedSupport() || address<1:0> = ’00’ then
4591 R[t] = data;
4592 else // Can only apply before ARMv7
4593 R[t] = ROR(data, 8*UInt(address<1:0>));
4594#endif
4595
4596 bool success = false;
4597 const uint32_t opcode = OpcodeAsUnsigned (&success);
4598 if (!success)
4599 return false;
4600
4601 if (ConditionPassed ())
4602 {
4603 const uint32_t addr_byte_size = GetAddressByteSize();
4604
4605 uint32_t t;
4606 uint32_t n;
4607 uint32_t imm32;
4608 bool index;
4609 bool add;
4610 bool wback;
4611
4612 switch (encoding)
4613 {
4614 case eEncodingA1:
4615 // if Rn == ’1111’ then SEE LDR (literal);
4616 // if P == ’0’ && W == ’1’ then SEE LDRT;
4617 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
4618 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4619 t = Bits32 (opcode, 15, 12);
4620 n = Bits32 (opcode, 19, 16);
4621 imm32 = Bits32 (opcode, 11, 0);
4622
4623 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4624 index = BitIsSet (opcode, 24);
4625 add = BitIsSet (opcode, 23);
4626 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4627
4628 // if wback && n == t then UNPREDICTABLE;
4629 if (wback && (n == t))
4630 return false;
4631
4632 break;
4633
4634 default:
4635 return false;
4636 }
4637
4638 addr_t address;
4639 addr_t offset_addr;
4640 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4641 if (!success)
4642 return false;
4643
4644 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4645 if (add)
4646 offset_addr = base_address + imm32;
4647 else
4648 offset_addr = base_address - imm32;
4649
4650 // address = if index then offset_addr else R[n];
4651 if (index)
4652 address = offset_addr;
4653 else
4654 address = base_address;
4655
4656 // data = MemU[address,4];
4657
4658 Register base_reg;
4659 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4660
4661 EmulateInstruction::Context context;
4662 context.type = eContextRegisterLoad;
4663 context.SetRegisterPlusOffset (base_reg, address - base_address);
4664
4665 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4666 if (!success)
4667 return false;
4668
4669 // if wback then R[n] = offset_addr;
4670 if (wback)
4671 {
4672 context.type = eContextAdjustBaseRegister;
4673 context.SetAddress (offset_addr);
4674 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4675 return false;
4676 }
4677
4678 // if t == 15 then
4679 if (t == 15)
4680 {
4681 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4682 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4683 {
4684 // LoadWritePC (data);
4685 context.type = eContextRegisterLoad;
4686 context.SetRegisterPlusOffset (base_reg, address - base_address);
4687 LoadWritePC (context, data);
4688 }
4689 else
4690 return false;
4691 }
4692 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4693 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4694 {
4695 // R[t] = data;
4696 context.type = eContextRegisterLoad;
4697 context.SetRegisterPlusOffset (base_reg, address - base_address);
4698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4699 return false;
4700 }
4701 // else // Can only apply before ARMv7
4702 else
4703 {
4704 // R[t] = ROR(data, 8*UInt(address<1:0>));
4705 data = ROR (data, Bits32 (address, 1, 0));
4706 context.type = eContextRegisterLoad;
4707 context.SetImmediate (data);
4708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4709 return false;
4710 }
4711
4712 }
4713 return true;
4714}
4715
Caroline Ticefe479112011-02-18 18:52:37 +00004716// LDR (register) calculates an address from a base register value and an offset register value, loads a word
4717// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
4718bool
4719EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
4720{
4721#if 0
4722 if ConditionPassed() then
4723 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4724 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4725 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4726 address = if index then offset_addr else R[n];
4727 data = MemU[address,4];
4728 if wback then R[n] = offset_addr;
4729 if t == 15 then
4730 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4731 elsif UnalignedSupport() || address<1:0> = ’00’ then
4732 R[t] = data;
4733 else // Can only apply before ARMv7
4734 if CurrentInstrSet() == InstrSet_ARM then
4735 R[t] = ROR(data, 8*UInt(address<1:0>));
4736 else
4737 R[t] = bits(32) UNKNOWN;
4738#endif
4739
4740 bool success = false;
4741 const uint32_t opcode = OpcodeAsUnsigned (&success);
4742 if (!success)
4743 return false;
4744
4745 if (ConditionPassed ())
4746 {
4747 const uint32_t addr_byte_size = GetAddressByteSize();
4748
4749 uint32_t t;
4750 uint32_t n;
4751 uint32_t m;
4752 bool index;
4753 bool add;
4754 bool wback;
4755 ARM_ShifterType shift_t;
4756 uint32_t shift_n;
4757
4758 switch (encoding)
4759 {
4760 case eEncodingT1:
4761 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4762 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4763 t = Bits32 (opcode, 2, 0);
4764 n = Bits32 (opcode, 5, 3);
4765 m = Bits32 (opcode, 8, 6);
4766
4767 // index = TRUE; add = TRUE; wback = FALSE;
4768 index = true;
4769 add = true;
4770 wback = false;
4771
4772 // (shift_t, shift_n) = (SRType_LSL, 0);
4773 shift_t = SRType_LSL;
4774 shift_n = 0;
4775
4776 break;
4777
4778 case eEncodingT2:
4779 // if Rn == ’1111’ then SEE LDR (literal);
4780 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4781 t = Bits32 (opcode, 15, 12);
4782 n = Bits32 (opcode, 19, 16);
4783 m = Bits32 (opcode, 3, 0);
4784
4785 // index = TRUE; add = TRUE; wback = FALSE;
4786 index = true;
4787 add = true;
4788 wback = false;
4789
4790 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4791 shift_t = SRType_LSL;
4792 shift_n = Bits32 (opcode, 5, 4);
4793
4794 // if BadReg(m) then UNPREDICTABLE;
4795 if (BadReg (m))
4796 return false;
4797
4798 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4799 if ((t == 15) && InITBlock() && !LastInITBlock())
4800 return false;
4801
4802 break;
4803
4804 case eEncodingA1:
4805 {
4806 // if P == ’0’ && W == ’1’ then SEE LDRT;
4807 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4808 t = Bits32 (opcode, 15, 12);
4809 n = Bits32 (opcode, 19, 16);
4810 m = Bits32 (opcode, 3, 0);
4811
4812 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4813 index = BitIsSet (opcode, 24);
4814 add = BitIsSet (opcode, 23);
4815 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4816
4817 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4818 uint32_t type = Bits32 (opcode, 6, 5);
4819 uint32_t imm5 = Bits32 (opcode, 11, 7);
4820 shift_n = DecodeImmShift (type, imm5, shift_t);
4821
4822 // if m == 15 then UNPREDICTABLE;
4823 if (m == 15)
4824 return false;
4825
4826 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4827 if (wback && ((n == 15) || (n == t)))
4828 return false;
4829 }
4830 break;
4831
4832
4833 default:
4834 return false;
4835 }
4836
4837 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4838 if (!success)
4839 return false;
4840
4841 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4842 if (!success)
4843 return false;
4844
4845 addr_t offset_addr;
4846 addr_t address;
4847
4848 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
4849 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, CPSR_C));
4850
4851 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4852 if (add)
4853 offset_addr = Rn + offset;
4854 else
4855 offset_addr = Rn - offset;
4856
4857 // address = if index then offset_addr else R[n];
4858 if (index)
4859 address = offset_addr;
4860 else
4861 address = Rn;
4862
4863 // data = MemU[address,4];
4864 Register base_reg;
4865 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4866
4867 EmulateInstruction::Context context;
4868 context.type = eContextRegisterLoad;
4869 context.SetRegisterPlusOffset (base_reg, address - Rn);
4870
4871 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
4872 if (!success)
4873 return false;
4874
4875 // if wback then R[n] = offset_addr;
4876 if (wback)
4877 {
4878 context.type = eContextAdjustBaseRegister;
4879 context.SetAddress (offset_addr);
4880 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4881 return false;
4882 }
4883
4884 // if t == 15 then
4885 if (t == 15)
4886 {
4887 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
4888 if (BitIsClear (address, 1) && BitIsClear (address, 0))
4889 {
4890 context.type = eContextRegisterLoad;
4891 context.SetRegisterPlusOffset (base_reg, address - Rn);
4892 LoadWritePC (context, data);
4893 }
4894 else
4895 return false;
4896 }
4897 // elsif UnalignedSupport() || address<1:0> = ’00’ then
4898 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4899 {
4900 // R[t] = data;
4901 context.type = eContextRegisterLoad;
4902 context.SetRegisterPlusOffset (base_reg, address - Rn);
4903 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4904 return false;
4905 }
4906 else // Can only apply before ARMv7
4907 {
4908 // if CurrentInstrSet() == InstrSet_ARM then
4909 if (CurrentInstrSet () == eModeARM)
4910 {
4911 // R[t] = ROR(data, 8*UInt(address<1:0>));
4912 data = ROR (data, Bits32 (address, 1, 0));
4913 context.type = eContextRegisterLoad;
4914 context.SetImmediate (data);
4915 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
4916 return false;
4917 }
4918 else
4919 {
4920 // R[t] = bits(32) UNKNOWN;
4921 WriteBits32Unknown (t);
4922 }
4923 }
4924 }
4925 return true;
4926}
Caroline Tice21b604b2011-02-18 21:06:04 +00004927
4928// LDRB (immediate, Thumb)
4929bool
4930EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
4931{
4932#if 0
4933 if ConditionPassed() then
4934 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4935 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4936 address = if index then offset_addr else R[n];
4937 R[t] = ZeroExtend(MemU[address,1], 32);
4938 if wback then R[n] = offset_addr;
4939#endif
4940
4941 bool success = false;
4942 const uint32_t opcode = OpcodeAsUnsigned (&success);
4943 if (!success)
4944 return false;
4945
4946 if (ConditionPassed ())
4947 {
4948 uint32_t t;
4949 uint32_t n;
4950 uint32_t imm32;
4951 bool index;
4952 bool add;
4953 bool wback;
4954
4955 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4956 switch (encoding)
4957 {
4958 case eEncodingT1:
4959 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4960 t = Bits32 (opcode, 2, 0);
4961 n = Bits32 (opcode, 5, 3);
4962 imm32 = Bits32 (opcode, 10, 6);
4963
4964 // index = TRUE; add = TRUE; wback = FALSE;
4965 index = true;
4966 add = true;
4967 wback= false;
4968
4969 break;
4970
4971 case eEncodingT2:
4972 // if Rt == ’1111’ then SEE PLD;
4973 // if Rn == ’1111’ then SEE LDRB (literal);
4974 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4975 t = Bits32 (opcode, 15, 12);
4976 n = Bits32 (opcode, 19, 16);
4977 imm32 = Bits32 (opcode, 11, 0);
4978
4979 // index = TRUE; add = TRUE; wback = FALSE;
4980 index = true;
4981 add = true;
4982 wback = false;
4983
4984 // if t == 13 then UNPREDICTABLE;
4985 if (t == 13)
4986 return false;
4987
4988 break;
4989
4990 case eEncodingT3:
4991 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
4992 // if Rn == ’1111’ then SEE LDRB (literal);
4993 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
4994 // if P == ’0’ && W == ’0’ then UNDEFINED;
4995 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
4996 return false;
4997
4998 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4999 t = Bits32 (opcode, 15, 12);
5000 n = Bits32 (opcode, 19, 16);
5001 imm32 = Bits32 (opcode, 7, 0);
5002
5003 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5004 index = BitIsSet (opcode, 10);
5005 add = BitIsSet (opcode, 9);
5006 wback = BitIsSet (opcode, 8);
5007
5008 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5009 if (BadReg (t) || (wback && (n == t)))
5010 return false;
5011
5012 break;
5013
5014 default:
5015 return false;
5016 }
5017
5018 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5019 if (!success)
5020 return false;
5021
5022 addr_t address;
5023 addr_t offset_addr;
5024
5025 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5026 if (add)
5027 offset_addr = Rn + imm32;
5028 else
5029 offset_addr = Rn - imm32;
5030
5031 // address = if index then offset_addr else R[n];
5032 if (index)
5033 address = offset_addr;
5034 else
5035 address = Rn;
5036
5037 // R[t] = ZeroExtend(MemU[address,1], 32);
5038 Register base_reg;
5039 Register data_reg;
5040 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5041 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5042
5043 EmulateInstruction::Context context;
5044 context.type = eContextRegisterLoad;
5045 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5046
5047 uint64_t data = MemURead (context, address, 1, 0, &success);
5048 if (!success)
5049 return false;
5050
5051 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5052 return false;
5053
5054 // if wback then R[n] = offset_addr;
5055 if (wback)
5056 {
5057 context.type = eContextAdjustBaseRegister;
5058 context.SetAddress (offset_addr);
5059 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5060 return false;
5061 }
5062 }
5063 return true;
5064}
Caroline Ticef55261f2011-02-18 22:24:22 +00005065
5066// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5067// zero-extends it to form a 32-bit word and writes it to a register.
5068bool
5069EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5070{
5071#if 0
5072 if ConditionPassed() then
5073 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5074 base = Align(PC,4);
5075 address = if add then (base + imm32) else (base - imm32);
5076 R[t] = ZeroExtend(MemU[address,1], 32);
5077#endif
5078
5079 bool success = false;
5080 const uint32_t opcode = OpcodeAsUnsigned (&success);
5081 if (!success)
5082 return false;
5083
5084 if (ConditionPassed ())
5085 {
5086 uint32_t t;
5087 uint32_t imm32;
5088 bool add;
5089 switch (encoding)
5090 {
5091 case eEncodingT1:
5092 // if Rt == ’1111’ then SEE PLD;
5093 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5094 t = Bits32 (opcode, 15, 12);
5095 imm32 = Bits32 (opcode, 11, 0);
5096 add = BitIsSet (opcode, 23);
5097
5098 // if t == 13 then UNPREDICTABLE;
5099 if (t == 13)
5100 return false;
5101
5102 break;
5103
5104 case eEncodingA1:
5105 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5106 t = Bits32 (opcode, 15, 12);
5107 imm32 = Bits32 (opcode, 11, 0);
5108 add = BitIsSet (opcode, 23);
5109
5110 // if t == 15 then UNPREDICTABLE;
5111 if (t == 15)
5112 return false;
5113 break;
5114
5115 default:
5116 return false;
5117 }
5118
5119 // base = Align(PC,4);
5120 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5121 if (!success)
5122 return false;
5123
5124 uint32_t base = AlignPC (pc_val);
5125
5126 addr_t address;
5127 // address = if add then (base + imm32) else (base - imm32);
5128 if (add)
5129 address = base + imm32;
5130 else
5131 address = base - imm32;
5132
5133 // R[t] = ZeroExtend(MemU[address,1], 32);
5134 EmulateInstruction::Context context;
5135 context.type = eContextRelativeBranchImmediate;
5136 context.SetImmediate (address - base);
5137
5138 uint64_t data = MemURead (context, address, 1, 0, &success);
5139 if (!success)
5140 return false;
5141
5142 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5143 return false;
5144 }
5145 return true;
5146}
Caroline Ticefe479112011-02-18 18:52:37 +00005147
Johnny Chen7c5234d2011-02-18 23:41:11 +00005148// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
5149// writes the result to the destination register. It can optionally update the condition flags based
5150// on the result.
5151bool
5152EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
5153{
5154#if 0
5155 // ARM pseudo code...
5156 if ConditionPassed() then
5157 EncodingSpecificOperations();
5158 result = R[n] OR imm32;
5159 if d == 15 then // Can only occur for ARM encoding
5160 ALUWritePC(result); // setflags is always FALSE here
5161 else
5162 R[d] = result;
5163 if setflags then
5164 APSR.N = result<31>;
5165 APSR.Z = IsZeroBit(result);
5166 APSR.C = carry;
5167 // APSR.V unchanged
5168#endif
5169
5170 bool success = false;
5171 const uint32_t opcode = OpcodeAsUnsigned (&success);
5172 if (!success)
5173 return false;
5174
5175 if (ConditionPassed())
5176 {
5177 uint32_t Rd, Rn;
5178 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
5179 bool setflags;
5180 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5181 switch (encoding)
5182 {
5183 case eEncodingT1:
5184 Rd = Bits32(opcode, 11, 8);
5185 Rn = Bits32(opcode, 19, 16);
5186 setflags = BitIsSet(opcode, 20);
5187 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5188 // if Rn == ‘1111’ then SEE MOV (immediate);
5189 if (Rn == 15)
5190 return EmulateMOVRdImm(eEncodingT2);
5191 if (BadReg(Rd) || Rn == 13)
5192 return false;
5193 break;
5194 case eEncodingA1:
5195 Rd = Bits32(opcode, 15, 12);
5196 Rn = Bits32(opcode, 19, 16);
5197 setflags = BitIsSet(opcode, 20);
5198 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5199 // TODO: Emulate SUBS PC, LR and related instructions.
5200 if (Rd == 15 && setflags)
5201 return false;
5202 break;
5203 default:
5204 return false;
5205 }
5206
5207 // Read the first operand.
5208 uint32_t val1 = ReadCoreReg(Rn, &success);
5209 if (!success)
5210 return false;
5211
5212 uint32_t result = val1 | imm32;
5213
5214 EmulateInstruction::Context context;
5215 context.type = EmulateInstruction::eContextImmediate;
5216 context.SetNoArgs ();
5217
5218 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5219 return false;
5220 }
5221 return true;
5222}
5223
5224// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
5225// value, and writes the result to the destination register. It can optionally update the condition flags based
5226// on the result.
5227bool
5228EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
5229{
5230#if 0
5231 // ARM pseudo code...
5232 if ConditionPassed() then
5233 EncodingSpecificOperations();
5234 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5235 result = R[n] OR shifted;
5236 if d == 15 then // Can only occur for ARM encoding
5237 ALUWritePC(result); // setflags is always FALSE here
5238 else
5239 R[d] = result;
5240 if setflags then
5241 APSR.N = result<31>;
5242 APSR.Z = IsZeroBit(result);
5243 APSR.C = carry;
5244 // APSR.V unchanged
5245#endif
5246
5247 bool success = false;
5248 const uint32_t opcode = OpcodeAsUnsigned (&success);
5249 if (!success)
5250 return false;
5251
5252 if (ConditionPassed())
5253 {
5254 uint32_t Rd, Rn, Rm;
5255 ARM_ShifterType shift_t;
5256 uint32_t shift_n; // the shift applied to the value read from Rm
5257 bool setflags;
5258 uint32_t carry;
5259 switch (encoding)
5260 {
5261 case eEncodingT1:
5262 Rd = Rn = Bits32(opcode, 2, 0);
5263 Rm = Bits32(opcode, 5, 3);
5264 setflags = !InITBlock();
5265 shift_t = SRType_LSL;
5266 shift_n = 0;
5267 case eEncodingT2:
5268 Rd = Bits32(opcode, 11, 8);
5269 Rn = Bits32(opcode, 19, 16);
5270 Rm = Bits32(opcode, 3, 0);
5271 setflags = BitIsSet(opcode, 20);
5272 shift_n = DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
5273 // if Rn == ‘1111’ then SEE MOV (register);
5274 if (Rn == 15)
5275 return EmulateMOVRdRm(eEncodingT3);
5276 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
5277 return false;
5278 break;
5279 case eEncodingA1:
5280 Rd = Bits32(opcode, 15, 12);
5281 Rn = Bits32(opcode, 19, 16);
5282 Rm = Bits32(opcode, 3, 0);
5283 setflags = BitIsSet(opcode, 20);
5284 shift_n = DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
5285 // TODO: Emulate SUBS PC, LR and related instructions.
5286 if (Rd == 15 && setflags)
5287 return false;
5288 break;
5289 default:
5290 return false;
5291 }
5292
5293 // Read the first operand.
5294 uint32_t val1 = ReadCoreReg(Rn, &success);
5295 if (!success)
5296 return false;
5297
5298 // Read the second operand.
5299 uint32_t val2 = ReadCoreReg(Rm, &success);
5300 if (!success)
5301 return false;
5302
5303 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5304 uint32_t result = val1 & shifted;
5305
5306 EmulateInstruction::Context context;
5307 context.type = EmulateInstruction::eContextImmediate;
5308 context.SetNoArgs ();
5309
5310 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5311 return false;
5312 }
5313 return true;
5314}
5315
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005316EmulateInstructionARM::ARMOpcode*
5317EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00005318{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005319 static ARMOpcode
5320 g_arm_opcodes[] =
5321 {
5322 //----------------------------------------------------------------------
5323 // Prologue instructions
5324 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00005325
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005326 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005327 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5328 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00005329
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005330 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005331 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005332 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00005333 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00005334 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
5335 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00005336 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00005337
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005338 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005339 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00005340
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005341 // push one register
5342 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00005343 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00005344
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005345 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00005346 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5347 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00005348
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005349 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00005350 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005351 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00005352
Johnny Chen9f687722011-02-18 00:02:28 +00005353 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5354 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00005355 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005356 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
5357
5358 //----------------------------------------------------------------------
5359 // Supervisor Call (previously Software Interrupt)
5360 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005361 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
5362
5363 //----------------------------------------------------------------------
5364 // Branch instructions
5365 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005366 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00005367 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
5368 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5369 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5370 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005371 // for example, "bx lr"
5372 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005373
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005374 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00005375 // Data-processing instructions
5376 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005377 // adc (immediate)
5378 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
5379 // adc (register)
5380 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005381 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005382 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00005383 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005384 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005385 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005386 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005387 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00005388 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005389 // orr (immediate)
5390 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
5391 // orr (register)
5392 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen28070c32011-02-12 01:27:26 +00005393 // move bitwise not
Johnny Chen157b9592011-02-18 21:13:05 +00005394 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005395 // asr (immediate)
5396 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005397 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00005398 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005399 // lsl (immediate)
5400 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
5401 // lsl (register)
5402 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
5403 // lsr (immediate)
5404 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
5405 // lsr (register)
5406 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005407 // rrx is a special case encoding of ror (immediate)
5408 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
5409 // ror (immediate)
5410 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
5411 // ror (register)
5412 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005413
5414 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005415 // Load instructions
5416 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00005417 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00005418 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00005419 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00005420 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00005421 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00005422 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00005423 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Ticefa172202011-02-11 22:49:54 +00005424
5425 //----------------------------------------------------------------------
5426 // Store instructions
5427 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00005428 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005429 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00005430 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00005431 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
5432 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00005433
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005434
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005435 };
5436 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
5437
5438 for (size_t i=0; i<k_num_arm_opcodes; ++i)
5439 {
5440 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
5441 return &g_arm_opcodes[i];
5442 }
5443 return NULL;
5444}
Greg Clayton64c84432011-01-21 22:02:52 +00005445
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005446
5447EmulateInstructionARM::ARMOpcode*
5448EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00005449{
Johnny Chenfdd179e2011-01-31 20:09:28 +00005450
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005451 static ARMOpcode
5452 g_thumb_opcodes[] =
5453 {
5454 //----------------------------------------------------------------------
5455 // Prologue instructions
5456 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00005457
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005458 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00005459 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
5460 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
5461 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00005462
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005463 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00005464 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005465 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00005466 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00005467 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00005468 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00005469
Johnny Chen864a8e82011-02-18 00:07:39 +00005470 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00005471 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00005472
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005473 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00005474 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
5475 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "add sp, sp, #imm"},
5476 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
5477 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005478
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005479 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00005480 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
5481 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00005482
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005483 //----------------------------------------------------------------------
5484 // Epilogue instructions
5485 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00005486
Johnny Chen864a8e82011-02-18 00:07:39 +00005487 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00005488 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
5489 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
5490 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00005491 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
5492 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00005493
5494 //----------------------------------------------------------------------
5495 // Supervisor Call (previously Software Interrupt)
5496 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00005497 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
5498
5499 //----------------------------------------------------------------------
5500 // If Then makes up to four following instructions conditional.
5501 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00005502 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
5503
5504 //----------------------------------------------------------------------
5505 // Branch instructions
5506 //----------------------------------------------------------------------
5507 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
5508 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
5509 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00005510 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005511 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00005512 // J1 == J2 == 1
5513 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
5514 // J1 == J2 == 1
5515 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
5516 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00005517 // for example, "bx lr"
5518 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00005519 // compare and branch
5520 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00005521 // table branch byte
5522 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
5523 // table branch halfword
5524 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005525
5526 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00005527 // Data-processing instructions
5528 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00005529 // adc (immediate)
5530 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
5531 // adc (register)
5532 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
5533 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
5534 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00005535 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005536 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00005537 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005538 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00005539 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00005540 // and (register)
5541 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
5542 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005543 // orr (immediate)
5544 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
5545 // orr (register)
5546 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
5547 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
5548
Johnny Chen338bf542011-02-10 19:29:03 +00005549 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00005550 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00005551 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00005552 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00005553 // mov{s}<c>.w <Rd>, <Rm>
5554 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00005555 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005556 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
5557 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chen28070c32011-02-12 01:27:26 +00005558 // move bitwise not
Johnny Chen9f687722011-02-18 00:02:28 +00005559 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNRdImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend4dc4442011-02-11 02:02:56 +00005560 // compare a register with immediate
Johnny Chen9f687722011-02-18 00:02:28 +00005561 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnImm, "cmp<c> <Rn>, #imm8"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005562 // compare Rn with Rm (Rn and Rm both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005563 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chene4a4d302011-02-11 21:53:58 +00005564 // compare Rn with Rm (Rn and Rm not both from r0-r7)
Johnny Chen9f687722011-02-18 00:02:28 +00005565 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPRnRm, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00005566 // asr (immediate)
5567 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00005568 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00005569 // asr (register)
5570 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
5571 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005572 // lsl (immediate)
5573 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
5574 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
5575 // lsl (register)
5576 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
5577 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
5578 // lsr (immediate)
5579 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
5580 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
5581 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00005582 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00005583 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00005584 // rrx is a special case encoding of ror (immediate)
5585 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
5586 // ror (immediate)
5587 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
5588 // ror (register)
5589 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
5590 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00005591
5592 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00005593 // Load instructions
5594 //----------------------------------------------------------------------
5595 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00005596 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00005597 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00005598 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
5599 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00005600 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00005601 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
5602 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00005603 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
5604 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
5605 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00005606 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Ticefa172202011-02-11 22:49:54 +00005607
5608 //----------------------------------------------------------------------
5609 // Store instructions
5610 //----------------------------------------------------------------------
5611 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00005612 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00005613 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00005614 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
5615 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
5616 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
5617 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
5618 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
5619 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
5620 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
5621 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
5622 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00005623 };
5624
5625 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
5626 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
5627 {
5628 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
5629 return &g_thumb_opcodes[i];
5630 }
5631 return NULL;
5632}
Greg Clayton64c84432011-01-21 22:02:52 +00005633
Greg Clayton31e2a382011-01-30 20:03:56 +00005634bool
Greg Clayton395fc332011-02-15 21:59:32 +00005635EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00005636{
5637 m_arm_isa = 0;
Greg Clayton395fc332011-02-15 21:59:32 +00005638 const char *arch_cstr = arch.AsCString ();
5639 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00005640 {
Greg Clayton395fc332011-02-15 21:59:32 +00005641 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
5642 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
5643 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
5644 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
5645 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
5646 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
5647 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
5648 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
5649 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
5650 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00005651 }
5652 return m_arm_isa != 0;
5653}
5654
5655
Greg Clayton64c84432011-01-21 22:02:52 +00005656bool
5657EmulateInstructionARM::ReadInstruction ()
5658{
5659 bool success = false;
5660 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
5661 if (success)
5662 {
5663 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
5664 if (success)
5665 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00005666 Context read_inst_context;
5667 read_inst_context.type = eContextReadOpcode;
5668 read_inst_context.SetNoArgs ();
5669
Greg Clayton64c84432011-01-21 22:02:52 +00005670 if (m_inst_cpsr & MASK_CPSR_T)
5671 {
5672 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005673 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005674
5675 if (success)
5676 {
5677 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
5678 {
5679 m_inst.opcode_type = eOpcode16;
5680 m_inst.opcode.inst16 = thumb_opcode;
5681 }
5682 else
5683 {
5684 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005685 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005686 }
5687 }
5688 }
5689 else
5690 {
5691 m_inst_mode = eModeARM;
5692 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00005693 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00005694 }
5695 }
5696 }
5697 if (!success)
5698 {
5699 m_inst_mode = eModeInvalid;
5700 m_inst_pc = LLDB_INVALID_ADDRESS;
5701 }
5702 return success;
5703}
5704
Johnny Chenee9b1f72011-02-09 01:00:31 +00005705uint32_t
5706EmulateInstructionARM::ArchVersion ()
5707{
5708 return m_arm_isa;
5709}
5710
Greg Clayton64c84432011-01-21 22:02:52 +00005711bool
5712EmulateInstructionARM::ConditionPassed ()
5713{
5714 if (m_inst_cpsr == 0)
5715 return false;
5716
5717 const uint32_t cond = CurrentCond ();
5718
5719 if (cond == UINT32_MAX)
5720 return false;
5721
5722 bool result = false;
5723 switch (UnsignedBits(cond, 3, 1))
5724 {
5725 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
5726 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
5727 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
5728 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
5729 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
5730 case 5:
5731 {
5732 bool n = (m_inst_cpsr & MASK_CPSR_N);
5733 bool v = (m_inst_cpsr & MASK_CPSR_V);
5734 result = n == v;
5735 }
5736 break;
5737 case 6:
5738 {
5739 bool n = (m_inst_cpsr & MASK_CPSR_N);
5740 bool v = (m_inst_cpsr & MASK_CPSR_V);
5741 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
5742 }
5743 break;
5744 case 7:
5745 result = true;
5746 break;
5747 }
5748
5749 if (cond & 1)
5750 result = !result;
5751 return result;
5752}
5753
Johnny Chen9ee056b2011-02-08 00:06:35 +00005754uint32_t
5755EmulateInstructionARM::CurrentCond ()
5756{
5757 switch (m_inst_mode)
5758 {
5759 default:
5760 case eModeInvalid:
5761 break;
5762
5763 case eModeARM:
5764 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
5765
5766 case eModeThumb:
5767 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
5768 // 'cond' field of the encoding.
5769 if (m_inst.opcode_type == eOpcode16 &&
5770 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
5771 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
5772 {
5773 return Bits32(m_inst.opcode.inst16, 11, 7);
5774 }
5775 else if (m_inst.opcode_type == eOpcode32 &&
5776 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
5777 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
5778 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
5779 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
5780 {
5781 return Bits32(m_inst.opcode.inst32, 25, 22);
5782 }
5783
5784 return m_it_session.GetCond();
5785 }
5786 return UINT32_MAX; // Return invalid value
5787}
5788
Johnny Chen9ee056b2011-02-08 00:06:35 +00005789bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00005790EmulateInstructionARM::InITBlock()
5791{
5792 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
5793}
5794
5795bool
5796EmulateInstructionARM::LastInITBlock()
5797{
5798 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
5799}
5800
5801bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00005802EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
5803{
5804 addr_t target;
5805
Johnny Chenee9b1f72011-02-09 01:00:31 +00005806 // Check the current instruction set.
5807 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005808 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005809 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00005810 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005811
Johnny Chen9ee056b2011-02-08 00:06:35 +00005812 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005813 return false;
5814
5815 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005816}
5817
5818// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
5819bool
Johnny Chen668b4512011-02-15 21:08:58 +00005820EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00005821{
5822 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00005823 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
5824 // we want to record it and issue a WriteRegister callback so the clients
5825 // can track the mode changes accordingly.
5826 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005827
5828 if (BitIsSet(addr, 0))
5829 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005830 if (CurrentInstrSet() != eModeThumb)
5831 {
5832 SelectInstrSet(eModeThumb);
5833 cpsr_changed = true;
5834 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005835 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00005836 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005837 }
5838 else if (BitIsClear(addr, 1))
5839 {
Johnny Chen0f309db2011-02-09 19:11:32 +00005840 if (CurrentInstrSet() != eModeARM)
5841 {
5842 SelectInstrSet(eModeARM);
5843 cpsr_changed = true;
5844 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005845 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00005846 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00005847 }
5848 else
5849 return false; // address<1:0> == '10' => UNPREDICTABLE
5850
Johnny Chen0f309db2011-02-09 19:11:32 +00005851 if (cpsr_changed)
5852 {
Johnny Chen558133b2011-02-09 23:59:17 +00005853 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00005854 return false;
5855 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00005856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00005857 return false;
5858
5859 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00005860}
Greg Clayton64c84432011-01-21 22:02:52 +00005861
Johnny Chenee9b1f72011-02-09 01:00:31 +00005862// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
5863bool
Johnny Chen668b4512011-02-15 21:08:58 +00005864EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00005865{
5866 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00005867 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00005868 else
5869 return BranchWritePC((const Context)context, addr);
5870}
5871
Johnny Chen26863dc2011-02-09 23:43:29 +00005872// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
5873bool
Johnny Chen668b4512011-02-15 21:08:58 +00005874EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00005875{
5876 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00005877 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00005878 else
5879 return BranchWritePC((const Context)context, addr);
5880}
5881
Johnny Chenee9b1f72011-02-09 01:00:31 +00005882EmulateInstructionARM::Mode
5883EmulateInstructionARM::CurrentInstrSet ()
5884{
5885 return m_inst_mode;
5886}
5887
5888// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00005889// ReadInstruction() is performed. This function has a side effect of updating
5890// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00005891bool
5892EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
5893{
Johnny Chen558133b2011-02-09 23:59:17 +00005894 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005895 switch (arm_or_thumb)
5896 {
5897 default:
5898 return false;
5899 eModeARM:
5900 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005901 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005902 break;
5903 eModeThumb:
5904 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00005905 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00005906 break;
5907 }
5908 return true;
5909}
5910
Johnny Chenef21b592011-02-10 01:52:38 +00005911// This function returns TRUE if the processor currently provides support for
5912// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
5913// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
5914bool
5915EmulateInstructionARM::UnalignedSupport()
5916{
5917 return (ArchVersion() >= ARMv7);
5918}
5919
Johnny Chenbf6ad172011-02-11 01:29:53 +00005920// The main addition and subtraction instructions can produce status information
5921// about both unsigned carry and signed overflow conditions. This status
5922// information can be used to synthesize multi-word additions and subtractions.
5923EmulateInstructionARM::AddWithCarryResult
5924EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
5925{
5926 uint32_t result;
5927 uint8_t carry_out;
5928 uint8_t overflow;
5929
5930 uint64_t unsigned_sum = x + y + carry_in;
5931 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
5932
5933 result = UnsignedBits(unsigned_sum, 31, 0);
5934 carry_out = (result == unsigned_sum ? 0 : 1);
5935 overflow = ((int32_t)result == signed_sum ? 0 : 1);
5936
5937 AddWithCarryResult res = { result, carry_out, overflow };
5938 return res;
5939}
5940
Johnny Chen157b9592011-02-18 21:13:05 +00005941uint32_t
5942EmulateInstructionARM::ReadCoreReg(uint32_t regnum, bool *success)
5943{
5944 uint32_t val;
5945 if (regnum == 15)
5946 {
5947 val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, success);
5948 if (CurrentInstrSet() == eModeThumb)
5949 val += 4;
5950 else
5951 val += 8;
5952 }
5953 else
5954 val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + regnum, 0, success);
5955
5956 return val;
5957}
5958
Johnny Chenca67d1c2011-02-17 01:35:27 +00005959// Write the result to the ARM core register Rd, and optionally update the
5960// condition flags based on the result.
5961//
5962// This helper method tries to encapsulate the following pseudocode from the
5963// ARM Architecture Reference Manual:
5964//
5965// if d == 15 then // Can only occur for encoding A1
5966// ALUWritePC(result); // setflags is always FALSE here
5967// else
5968// R[d] = result;
5969// if setflags then
5970// APSR.N = result<31>;
5971// APSR.Z = IsZeroBit(result);
5972// APSR.C = carry;
5973// // APSR.V unchanged
5974//
5975// In the above case, the API client does not pass in the overflow arg, which
5976// defaults to ~0u.
5977bool
Johnny Chen10530c22011-02-17 22:37:12 +00005978EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
5979 const uint32_t result,
5980 const uint32_t Rd,
5981 bool setflags,
5982 const uint32_t carry,
5983 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00005984{
5985 if (Rd == 15)
5986 {
5987 if (!ALUWritePC (context, result))
5988 return false;
5989 }
5990 else
5991 {
5992 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
5993 return false;
5994 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00005995 return WriteFlags (context, result, carry, overflow);
5996 }
5997 return true;
5998}
5999
6000// This helper method tries to encapsulate the following pseudocode from the
6001// ARM Architecture Reference Manual:
6002//
6003// APSR.N = result<31>;
6004// APSR.Z = IsZeroBit(result);
6005// APSR.C = carry;
6006// APSR.V = overflow
6007//
6008// Default arguments can be specified for carry and overflow parameters, which means
6009// not to update the respective flags.
6010bool
6011EmulateInstructionARM::WriteFlags (Context &context,
6012 const uint32_t result,
6013 const uint32_t carry,
6014 const uint32_t overflow)
6015{
6016 m_new_inst_cpsr = m_inst_cpsr;
6017 SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
6018 SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
6019 if (carry != ~0u)
6020 SetBit32(m_new_inst_cpsr, CPSR_C, carry);
6021 if (overflow != ~0u)
6022 SetBit32(m_new_inst_cpsr, CPSR_V, overflow);
6023 if (m_new_inst_cpsr != m_inst_cpsr)
6024 {
6025 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
6026 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00006027 }
6028 return true;
6029}
6030
Greg Clayton64c84432011-01-21 22:02:52 +00006031bool
6032EmulateInstructionARM::EvaluateInstruction ()
6033{
Johnny Chenc315f862011-02-05 00:46:10 +00006034 // Advance the ITSTATE bits to their values for the next instruction.
6035 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
6036 m_it_session.ITAdvance();
6037
Greg Clayton64c84432011-01-21 22:02:52 +00006038 return false;
6039}