1 //===-- 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
10 #include <stdlib.h>
11
12 #include "EmulateInstructionARM.h"
13 #include "EmulationStateARM.h"
14 #include "lldb/Core/ArchSpec.h"
15 #include "lldb/Core/Address.h"
16 #include "lldb/Core/ConstString.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Interpreter/OptionValueArray.h"
20 #include "lldb/Interpreter/OptionValueDictionary.h"
21 #include "lldb/Symbol/UnwindPlan.h"
22
23 #include "Plugins/Process/Utility/ARMDefines.h"
24 #include "Plugins/Process/Utility/ARMUtils.h"
25 #include "Utility/ARM_DWARF_Registers.h"
26
27 #include "llvm/Support/MathExtras.h" // for SignExtend32 template function
28 // and countTrailingZeros function
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 // Convenient macro definitions.
34 #define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
35 #define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
36
37 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
38
39 //----------------------------------------------------------------------
40 //
41 // ITSession implementation
42 //
43 //----------------------------------------------------------------------
44
45 // A8.6.50
46 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
47 static uint32_t
CountITSize(uint32_t ITMask)48 CountITSize (uint32_t ITMask) {
49 // First count the trailing zeros of the IT mask.
50 uint32_t TZ = llvm::countTrailingZeros(ITMask);
51 if (TZ > 3)
52 {
53 #ifdef LLDB_CONFIGURATION_DEBUG
54 printf("Encoding error: IT Mask '0000'\n");
55 #endif
56 return 0;
57 }
58 return (4 - TZ);
59 }
60
61 // Init ITState. Note that at least one bit is always 1 in mask.
InitIT(uint32_t bits7_0)62 bool ITSession::InitIT(uint32_t bits7_0)
63 {
64 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
65 if (ITCounter == 0)
66 return false;
67
68 // A8.6.50 IT
69 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
70 if (FirstCond == 0xF)
71 {
72 #ifdef LLDB_CONFIGURATION_DEBUG
73 printf("Encoding error: IT FirstCond '1111'\n");
74 #endif
75 return false;
76 }
77 if (FirstCond == 0xE && ITCounter != 1)
78 {
79 #ifdef LLDB_CONFIGURATION_DEBUG
80 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
81 #endif
82 return false;
83 }
84
85 ITState = bits7_0;
86 return true;
87 }
88
89 // Update ITState if necessary.
ITAdvance()90 void ITSession::ITAdvance()
91 {
92 //assert(ITCounter);
93 --ITCounter;
94 if (ITCounter == 0)
95 ITState = 0;
96 else
97 {
98 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
99 SetBits32(ITState, 4, 0, NewITState4_0);
100 }
101 }
102
103 // Return true if we're inside an IT Block.
InITBlock()104 bool ITSession::InITBlock()
105 {
106 return ITCounter != 0;
107 }
108
109 // Return true if we're the last instruction inside an IT Block.
LastInITBlock()110 bool ITSession::LastInITBlock()
111 {
112 return ITCounter == 1;
113 }
114
115 // Get condition bits for the current thumb instruction.
GetCond()116 uint32_t ITSession::GetCond()
117 {
118 if (InITBlock())
119 return Bits32(ITState, 7, 4);
120 else
121 return COND_AL;
122 }
123
124 // ARM constants used during decoding
125 #define REG_RD 0
126 #define LDM_REGLIST 1
127 #define SP_REG 13
128 #define LR_REG 14
129 #define PC_REG 15
130 #define PC_REGLIST_BIT 0x8000
131
132 #define ARMv4 (1u << 0)
133 #define ARMv4T (1u << 1)
134 #define ARMv5T (1u << 2)
135 #define ARMv5TE (1u << 3)
136 #define ARMv5TEJ (1u << 4)
137 #define ARMv6 (1u << 5)
138 #define ARMv6K (1u << 6)
139 #define ARMv6T2 (1u << 7)
140 #define ARMv7 (1u << 8)
141 #define ARMv7S (1u << 9)
142 #define ARMv8 (1u << 10)
143 #define ARMvAll (0xffffffffu)
144
145 #define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
146 #define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
147 #define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
148 #define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
149 #define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
150 #define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv7S|ARMv8)
151 #define ARMV7_ABOVE (ARMv7|ARMv7S|ARMv8)
152
153 #define No_VFP 0
154 #define VFPv1 (1u << 1)
155 #define VFPv2 (1u << 2)
156 #define VFPv3 (1u << 3)
157 #define AdvancedSIMD (1u << 4)
158
159 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
160 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
161 #define VFPv2v3 (VFPv2 | VFPv3)
162
163 //----------------------------------------------------------------------
164 //
165 // EmulateInstructionARM implementation
166 //
167 //----------------------------------------------------------------------
168
169 void
Initialize()170 EmulateInstructionARM::Initialize ()
171 {
172 PluginManager::RegisterPlugin (GetPluginNameStatic (),
173 GetPluginDescriptionStatic (),
174 CreateInstance);
175 }
176
177 void
Terminate()178 EmulateInstructionARM::Terminate ()
179 {
180 PluginManager::UnregisterPlugin (CreateInstance);
181 }
182
183 ConstString
GetPluginNameStatic()184 EmulateInstructionARM::GetPluginNameStatic ()
185 {
186 static ConstString g_name("arm");
187 return g_name;
188 }
189
190 const char *
GetPluginDescriptionStatic()191 EmulateInstructionARM::GetPluginDescriptionStatic ()
192 {
193 return "Emulate instructions for the ARM architecture.";
194 }
195
196 EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)197 EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
198 {
199 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
200 {
201 if (arch.GetTriple().getArch() == llvm::Triple::arm)
202 {
203 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
204
205 if (emulate_insn_ap.get())
206 return emulate_insn_ap.release();
207 }
208 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
209 {
210 std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
211
212 if (emulate_insn_ap.get())
213 return emulate_insn_ap.release();
214 }
215 }
216
217 return NULL;
218 }
219
220 bool
SetTargetTriple(const ArchSpec & arch)221 EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
222 {
223 if (arch.GetTriple().getArch () == llvm::Triple::arm)
224 return true;
225 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
226 return true;
227
228 return false;
229 }
230
231 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
232 bool
WriteBits32UnknownToMemory(addr_t address)233 EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
234 {
235 EmulateInstruction::Context context;
236 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
237 context.SetNoArgs ();
238
239 uint32_t random_data = rand ();
240 const uint32_t addr_byte_size = GetAddressByteSize();
241
242 if (!MemAWrite (context, address, random_data, addr_byte_size))
243 return false;
244
245 return true;
246 }
247
248 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
249 bool
WriteBits32Unknown(int n)250 EmulateInstructionARM::WriteBits32Unknown (int n)
251 {
252 EmulateInstruction::Context context;
253 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
254 context.SetNoArgs ();
255
256 bool success;
257 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
258
259 if (!success)
260 return false;
261
262 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
263 return false;
264
265 return true;
266 }
267
268 bool
GetRegisterInfo(uint32_t reg_kind,uint32_t reg_num,RegisterInfo & reg_info)269 EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo ®_info)
270 {
271 if (reg_kind == eRegisterKindGeneric)
272 {
273 switch (reg_num)
274 {
275 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
276 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
277 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
278 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
279 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
280 default: return false;
281 }
282 }
283
284 if (reg_kind == eRegisterKindDWARF)
285 return GetARMDWARFRegisterInfo(reg_num, reg_info);
286 return false;
287 }
288
289 uint32_t
GetFramePointerRegisterNumber() const290 EmulateInstructionARM::GetFramePointerRegisterNumber () const
291 {
292 if (m_opcode_mode == eModeThumb)
293 {
294 switch (m_arch.GetTriple().getOS())
295 {
296 case llvm::Triple::Darwin:
297 case llvm::Triple::MacOSX:
298 case llvm::Triple::IOS:
299 return 7;
300 default:
301 break;
302 }
303 }
304 return 11;
305 }
306
307 uint32_t
GetFramePointerDWARFRegisterNumber() const308 EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
309 {
310 if (m_opcode_mode == eModeThumb)
311 {
312 switch (m_arch.GetTriple().getOS())
313 {
314 case llvm::Triple::Darwin:
315 case llvm::Triple::MacOSX:
316 case llvm::Triple::IOS:
317 return dwarf_r7;
318 default:
319 break;
320 }
321 }
322 return dwarf_r11;
323 }
324
325 // Push Multiple Registers stores multiple registers to the stack, storing to
326 // consecutive memory locations ending just below the address in SP, and updates
327 // SP to point to the start of the stored data.
328 bool
EmulatePUSH(const uint32_t opcode,const ARMEncoding encoding)329 EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
330 {
331 #if 0
332 // ARM pseudo code...
333 if (ConditionPassed())
334 {
335 EncodingSpecificOperations();
336 NullCheckIfThumbEE(13);
337 address = SP - 4*BitCount(registers);
338
339 for (i = 0 to 14)
340 {
341 if (registers<i> == '1')
342 {
343 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
344 MemA[address,4] = bits(32) UNKNOWN;
345 else
346 MemA[address,4] = R[i];
347 address = address + 4;
348 }
349 }
350
351 if (registers<15> == '1') // Only possible for encoding A1 or A2
352 MemA[address,4] = PCStoreValue();
353
354 SP = SP - 4*BitCount(registers);
355 }
356 #endif
357
358 bool conditional = false;
359 bool success = false;
360 if (ConditionPassed(opcode, &conditional))
361 {
362 const uint32_t addr_byte_size = GetAddressByteSize();
363 const addr_t sp = ReadCoreReg (SP_REG, &success);
364 if (!success)
365 return false;
366 uint32_t registers = 0;
367 uint32_t Rt; // the source register
368 switch (encoding) {
369 case eEncodingT1:
370 registers = Bits32(opcode, 7, 0);
371 // The M bit represents LR.
372 if (Bit32(opcode, 8))
373 registers |= (1u << 14);
374 // if BitCount(registers) < 1 then UNPREDICTABLE;
375 if (BitCount(registers) < 1)
376 return false;
377 break;
378 case eEncodingT2:
379 // Ignore bits 15 & 13.
380 registers = Bits32(opcode, 15, 0) & ~0xa000;
381 // if BitCount(registers) < 2 then UNPREDICTABLE;
382 if (BitCount(registers) < 2)
383 return false;
384 break;
385 case eEncodingT3:
386 Rt = Bits32(opcode, 15, 12);
387 // if BadReg(t) then UNPREDICTABLE;
388 if (BadReg(Rt))
389 return false;
390 registers = (1u << Rt);
391 break;
392 case eEncodingA1:
393 registers = Bits32(opcode, 15, 0);
394 // Instead of return false, let's handle the following case as well,
395 // which amounts to pushing one reg onto the full descending stacks.
396 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
397 break;
398 case eEncodingA2:
399 Rt = Bits32(opcode, 15, 12);
400 // if t == 13 then UNPREDICTABLE;
401 if (Rt == dwarf_sp)
402 return false;
403 registers = (1u << Rt);
404 break;
405 default:
406 return false;
407 }
408 addr_t sp_offset = addr_byte_size * BitCount (registers);
409 addr_t addr = sp - sp_offset;
410 uint32_t i;
411
412 EmulateInstruction::Context context;
413 if (conditional)
414 context.type = EmulateInstruction::eContextRegisterStore;
415 else
416 context.type = EmulateInstruction::eContextPushRegisterOnStack;
417 RegisterInfo reg_info;
418 RegisterInfo sp_reg;
419 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
420 for (i=0; i<15; ++i)
421 {
422 if (BitIsSet (registers, i))
423 {
424 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
425 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
426 uint32_t reg_value = ReadCoreReg(i, &success);
427 if (!success)
428 return false;
429 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
430 return false;
431 addr += addr_byte_size;
432 }
433 }
434
435 if (BitIsSet (registers, 15))
436 {
437 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
438 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
439 const uint32_t pc = ReadCoreReg(PC_REG, &success);
440 if (!success)
441 return false;
442 if (!MemAWrite (context, addr, pc, addr_byte_size))
443 return false;
444 }
445
446 context.type = EmulateInstruction::eContextAdjustStackPointer;
447 context.SetImmediateSigned (-sp_offset);
448
449 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
450 return false;
451 }
452 return true;
453 }
454
455 // Pop Multiple Registers loads multiple registers from the stack, loading from
456 // consecutive memory locations staring at the address in SP, and updates
457 // SP to point just above the loaded data.
458 bool
EmulatePOP(const uint32_t opcode,const ARMEncoding encoding)459 EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
460 {
461 #if 0
462 // ARM pseudo code...
463 if (ConditionPassed())
464 {
465 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
466 address = SP;
467 for i = 0 to 14
468 if registers<i> == '1' then
469 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
470 if registers<15> == '1' then
471 if UnalignedAllowed then
472 LoadWritePC(MemU[address,4]);
473 else
474 LoadWritePC(MemA[address,4]);
475 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
476 if registers<13> == '1' then SP = bits(32) UNKNOWN;
477 }
478 #endif
479
480 bool success = false;
481
482 bool conditional = false;
483 if (ConditionPassed(opcode, &conditional))
484 {
485 const uint32_t addr_byte_size = GetAddressByteSize();
486 const addr_t sp = ReadCoreReg (SP_REG, &success);
487 if (!success)
488 return false;
489 uint32_t registers = 0;
490 uint32_t Rt; // the destination register
491 switch (encoding) {
492 case eEncodingT1:
493 registers = Bits32(opcode, 7, 0);
494 // The P bit represents PC.
495 if (Bit32(opcode, 8))
496 registers |= (1u << 15);
497 // if BitCount(registers) < 1 then UNPREDICTABLE;
498 if (BitCount(registers) < 1)
499 return false;
500 break;
501 case eEncodingT2:
502 // Ignore bit 13.
503 registers = Bits32(opcode, 15, 0) & ~0x2000;
504 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
505 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
506 return false;
507 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
508 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
509 return false;
510 break;
511 case eEncodingT3:
512 Rt = Bits32(opcode, 15, 12);
513 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
514 if (Rt == 13)
515 return false;
516 if (Rt == 15 && InITBlock() && !LastInITBlock())
517 return false;
518 registers = (1u << Rt);
519 break;
520 case eEncodingA1:
521 registers = Bits32(opcode, 15, 0);
522 // Instead of return false, let's handle the following case as well,
523 // which amounts to popping one reg from the full descending stacks.
524 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
525
526 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
527 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
528 return false;
529 break;
530 case eEncodingA2:
531 Rt = Bits32(opcode, 15, 12);
532 // if t == 13 then UNPREDICTABLE;
533 if (Rt == dwarf_sp)
534 return false;
535 registers = (1u << Rt);
536 break;
537 default:
538 return false;
539 }
540 addr_t sp_offset = addr_byte_size * BitCount (registers);
541 addr_t addr = sp;
542 uint32_t i, data;
543
544 EmulateInstruction::Context context;
545 if (conditional)
546 context.type = EmulateInstruction::eContextRegisterLoad;
547 else
548 context.type = EmulateInstruction::eContextPopRegisterOffStack;
549
550 RegisterInfo sp_reg;
551 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
552
553 for (i=0; i<15; ++i)
554 {
555 if (BitIsSet (registers, i))
556 {
557 context.SetRegisterPlusOffset (sp_reg, addr - sp);
558 data = MemARead(context, addr, 4, 0, &success);
559 if (!success)
560 return false;
561 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
562 return false;
563 addr += addr_byte_size;
564 }
565 }
566
567 if (BitIsSet (registers, 15))
568 {
569 context.SetRegisterPlusOffset (sp_reg, addr - sp);
570 data = MemARead(context, addr, 4, 0, &success);
571 if (!success)
572 return false;
573 // In ARMv5T and above, this is an interworking branch.
574 if (!LoadWritePC(context, data))
575 return false;
576 //addr += addr_byte_size;
577 }
578
579 context.type = EmulateInstruction::eContextAdjustStackPointer;
580 context.SetImmediateSigned (sp_offset);
581
582 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
583 return false;
584 }
585 return true;
586 }
587
588 // Set r7 or ip to point to saved value residing within the stack.
589 // ADD (SP plus immediate)
590 bool
EmulateADDRdSPImm(const uint32_t opcode,const ARMEncoding encoding)591 EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
592 {
593 #if 0
594 // ARM pseudo code...
595 if (ConditionPassed())
596 {
597 EncodingSpecificOperations();
598 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
599 if d == 15 then
600 ALUWritePC(result); // setflags is always FALSE here
601 else
602 R[d] = result;
603 if setflags then
604 APSR.N = result<31>;
605 APSR.Z = IsZeroBit(result);
606 APSR.C = carry;
607 APSR.V = overflow;
608 }
609 #endif
610
611 bool success = false;
612
613 if (ConditionPassed(opcode))
614 {
615 const addr_t sp = ReadCoreReg (SP_REG, &success);
616 if (!success)
617 return false;
618 uint32_t Rd; // the destination register
619 uint32_t imm32;
620 switch (encoding) {
621 case eEncodingT1:
622 Rd = 7;
623 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
624 break;
625 case eEncodingA1:
626 Rd = Bits32(opcode, 15, 12);
627 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
628 break;
629 default:
630 return false;
631 }
632 addr_t sp_offset = imm32;
633 addr_t addr = sp + sp_offset; // a pointer to the stack area
634
635 EmulateInstruction::Context context;
636 context.type = eContextSetFramePointer;
637 RegisterInfo sp_reg;
638 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
639 context.SetRegisterPlusOffset (sp_reg, sp_offset);
640
641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
642 return false;
643 }
644 return true;
645 }
646
647 // Set r7 or ip to the current stack pointer.
648 // MOV (register)
649 bool
EmulateMOVRdSP(const uint32_t opcode,const ARMEncoding encoding)650 EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
651 {
652 #if 0
653 // ARM pseudo code...
654 if (ConditionPassed())
655 {
656 EncodingSpecificOperations();
657 result = R[m];
658 if d == 15 then
659 ALUWritePC(result); // setflags is always FALSE here
660 else
661 R[d] = result;
662 if setflags then
663 APSR.N = result<31>;
664 APSR.Z = IsZeroBit(result);
665 // APSR.C unchanged
666 // APSR.V unchanged
667 }
668 #endif
669
670 bool success = false;
671
672 if (ConditionPassed(opcode))
673 {
674 const addr_t sp = ReadCoreReg (SP_REG, &success);
675 if (!success)
676 return false;
677 uint32_t Rd; // the destination register
678 switch (encoding) {
679 case eEncodingT1:
680 Rd = 7;
681 break;
682 case eEncodingA1:
683 Rd = 12;
684 break;
685 default:
686 return false;
687 }
688
689 EmulateInstruction::Context context;
690 if (Rd == GetFramePointerRegisterNumber())
691 context.type = EmulateInstruction::eContextSetFramePointer;
692 else
693 context.type = EmulateInstruction::eContextRegisterPlusOffset;
694 RegisterInfo sp_reg;
695 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
696 context.SetRegisterPlusOffset (sp_reg, 0);
697
698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
699 return false;
700 }
701 return true;
702 }
703
704 // Move from high register (r8-r15) to low register (r0-r7).
705 // MOV (register)
706 bool
EmulateMOVLowHigh(const uint32_t opcode,const ARMEncoding encoding)707 EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
708 {
709 return EmulateMOVRdRm (opcode, encoding);
710 }
711
712 // Move from register to register.
713 // MOV (register)
714 bool
EmulateMOVRdRm(const uint32_t opcode,const ARMEncoding encoding)715 EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
716 {
717 #if 0
718 // ARM pseudo code...
719 if (ConditionPassed())
720 {
721 EncodingSpecificOperations();
722 result = R[m];
723 if d == 15 then
724 ALUWritePC(result); // setflags is always FALSE here
725 else
726 R[d] = result;
727 if setflags then
728 APSR.N = result<31>;
729 APSR.Z = IsZeroBit(result);
730 // APSR.C unchanged
731 // APSR.V unchanged
732 }
733 #endif
734
735 bool success = false;
736
737 if (ConditionPassed(opcode))
738 {
739 uint32_t Rm; // the source register
740 uint32_t Rd; // the destination register
741 bool setflags;
742 switch (encoding) {
743 case eEncodingT1:
744 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
745 Rm = Bits32(opcode, 6, 3);
746 setflags = false;
747 if (Rd == 15 && InITBlock() && !LastInITBlock())
748 return false;
749 break;
750 case eEncodingT2:
751 Rd = Bits32(opcode, 2, 0);
752 Rm = Bits32(opcode, 5, 3);
753 setflags = true;
754 if (InITBlock())
755 return false;
756 break;
757 case eEncodingT3:
758 Rd = Bits32(opcode, 11, 8);
759 Rm = Bits32(opcode, 3, 0);
760 setflags = BitIsSet(opcode, 20);
761 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
762 if (setflags && (BadReg(Rd) || BadReg(Rm)))
763 return false;
764 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
765 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
766 return false;
767 break;
768 case eEncodingA1:
769 Rd = Bits32(opcode, 15, 12);
770 Rm = Bits32(opcode, 3, 0);
771 setflags = BitIsSet(opcode, 20);
772
773 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
774 if (Rd == 15 && setflags)
775 return EmulateSUBSPcLrEtc (opcode, encoding);
776 break;
777 default:
778 return false;
779 }
780 uint32_t result = ReadCoreReg(Rm, &success);
781 if (!success)
782 return false;
783
784 // The context specifies that Rm is to be moved into Rd.
785 EmulateInstruction::Context context;
786 context.type = EmulateInstruction::eContextRegisterLoad;
787 RegisterInfo dwarf_reg;
788 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
789 context.SetRegister (dwarf_reg);
790
791 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
792 return false;
793 }
794 return true;
795 }
796
797 // Move (immediate) writes an immediate value to the destination register. It
798 // can optionally update the condition flags based on the value.
799 // MOV (immediate)
800 bool
EmulateMOVRdImm(const uint32_t opcode,const ARMEncoding encoding)801 EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
802 {
803 #if 0
804 // ARM pseudo code...
805 if (ConditionPassed())
806 {
807 EncodingSpecificOperations();
808 result = imm32;
809 if d == 15 then // Can only occur for ARM encoding
810 ALUWritePC(result); // setflags is always FALSE here
811 else
812 R[d] = result;
813 if setflags then
814 APSR.N = result<31>;
815 APSR.Z = IsZeroBit(result);
816 APSR.C = carry;
817 // APSR.V unchanged
818 }
819 #endif
820
821 if (ConditionPassed(opcode))
822 {
823 uint32_t Rd; // the destination register
824 uint32_t imm32; // the immediate value to be written to Rd
825 uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
826 // for setflags == false, this value is a don't care
827 // initialized to 0 to silence the static analyzer
828 bool setflags;
829 switch (encoding) {
830 case eEncodingT1:
831 Rd = Bits32(opcode, 10, 8);
832 setflags = !InITBlock();
833 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
834 carry = APSR_C;
835
836 break;
837
838 case eEncodingT2:
839 Rd = Bits32(opcode, 11, 8);
840 setflags = BitIsSet(opcode, 20);
841 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
842 if (BadReg(Rd))
843 return false;
844
845 break;
846
847 case eEncodingT3:
848 {
849 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
850 Rd = Bits32 (opcode, 11, 8);
851 setflags = false;
852 uint32_t imm4 = Bits32 (opcode, 19, 16);
853 uint32_t imm3 = Bits32 (opcode, 14, 12);
854 uint32_t i = Bit32 (opcode, 26);
855 uint32_t imm8 = Bits32 (opcode, 7, 0);
856 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
857
858 // if BadReg(d) then UNPREDICTABLE;
859 if (BadReg (Rd))
860 return false;
861 }
862 break;
863
864 case eEncodingA1:
865 // d = UInt(Rd); setflags = (S == �1�); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
866 Rd = Bits32 (opcode, 15, 12);
867 setflags = BitIsSet (opcode, 20);
868 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
869
870 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
871 if ((Rd == 15) && setflags)
872 return EmulateSUBSPcLrEtc (opcode, encoding);
873
874 break;
875
876 case eEncodingA2:
877 {
878 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
879 Rd = Bits32 (opcode, 15, 12);
880 setflags = false;
881 uint32_t imm4 = Bits32 (opcode, 19, 16);
882 uint32_t imm12 = Bits32 (opcode, 11, 0);
883 imm32 = (imm4 << 12) | imm12;
884
885 // if d == 15 then UNPREDICTABLE;
886 if (Rd == 15)
887 return false;
888 }
889 break;
890
891 default:
892 return false;
893 }
894 uint32_t result = imm32;
895
896 // The context specifies that an immediate is to be moved into Rd.
897 EmulateInstruction::Context context;
898 context.type = EmulateInstruction::eContextImmediate;
899 context.SetNoArgs ();
900
901 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
902 return false;
903 }
904 return true;
905 }
906
907 // MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
908 // register. These 32 bits do not depend on whether the source register values are considered to be signed values or
909 // unsigned values.
910 //
911 // Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
912 // limited to only a few forms of the instruction.
913 bool
EmulateMUL(const uint32_t opcode,const ARMEncoding encoding)914 EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
915 {
916 #if 0
917 if ConditionPassed() then
918 EncodingSpecificOperations();
919 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
920 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
921 result = operand1 * operand2;
922 R[d] = result<31:0>;
923 if setflags then
924 APSR.N = result<31>;
925 APSR.Z = IsZeroBit(result);
926 if ArchVersion() == 4 then
927 APSR.C = bit UNKNOWN;
928 // else APSR.C unchanged
929 // APSR.V always unchanged
930 #endif
931
932 if (ConditionPassed(opcode))
933 {
934 uint32_t d;
935 uint32_t n;
936 uint32_t m;
937 bool setflags;
938
939 // EncodingSpecificOperations();
940 switch (encoding)
941 {
942 case eEncodingT1:
943 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
944 d = Bits32 (opcode, 2, 0);
945 n = Bits32 (opcode, 5, 3);
946 m = Bits32 (opcode, 2, 0);
947 setflags = !InITBlock();
948
949 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
950 if ((ArchVersion() < ARMv6) && (d == n))
951 return false;
952
953 break;
954
955 case eEncodingT2:
956 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
957 d = Bits32 (opcode, 11, 8);
958 n = Bits32 (opcode, 19, 16);
959 m = Bits32 (opcode, 3, 0);
960 setflags = false;
961
962 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
963 if (BadReg (d) || BadReg (n) || BadReg (m))
964 return false;
965
966 break;
967
968 case eEncodingA1:
969 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
970 d = Bits32 (opcode, 19, 16);
971 n = Bits32 (opcode, 3, 0);
972 m = Bits32 (opcode, 11, 8);
973 setflags = BitIsSet (opcode, 20);
974
975 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
976 if ((d == 15) || (n == 15) || (m == 15))
977 return false;
978
979 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
980 if ((ArchVersion() < ARMv6) && (d == n))
981 return false;
982
983 break;
984
985 default:
986 return false;
987 }
988
989 bool success = false;
990
991 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
992 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
993 if (!success)
994 return false;
995
996 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
997 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
998 if (!success)
999 return false;
1000
1001 // result = operand1 * operand2;
1002 uint64_t result = operand1 * operand2;
1003
1004 // R[d] = result<31:0>;
1005 RegisterInfo op1_reg;
1006 RegisterInfo op2_reg;
1007 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
1008 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
1009
1010 EmulateInstruction::Context context;
1011 context.type = eContextArithmetic;
1012 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
1013
1014 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
1015 return false;
1016
1017 // if setflags then
1018 if (setflags)
1019 {
1020 // APSR.N = result<31>;
1021 // APSR.Z = IsZeroBit(result);
1022 m_new_inst_cpsr = m_opcode_cpsr;
1023 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
1024 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1025 if (m_new_inst_cpsr != m_opcode_cpsr)
1026 {
1027 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1028 return false;
1029 }
1030
1031 // if ArchVersion() == 4 then
1032 // APSR.C = bit UNKNOWN;
1033 }
1034 }
1035 return true;
1036 }
1037
1038 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1039 // It can optionally update the condition flags based on the value.
1040 bool
EmulateMVNImm(const uint32_t opcode,const ARMEncoding encoding)1041 EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
1042 {
1043 #if 0
1044 // ARM pseudo code...
1045 if (ConditionPassed())
1046 {
1047 EncodingSpecificOperations();
1048 result = NOT(imm32);
1049 if d == 15 then // Can only occur for ARM encoding
1050 ALUWritePC(result); // setflags is always FALSE here
1051 else
1052 R[d] = result;
1053 if setflags then
1054 APSR.N = result<31>;
1055 APSR.Z = IsZeroBit(result);
1056 APSR.C = carry;
1057 // APSR.V unchanged
1058 }
1059 #endif
1060
1061 if (ConditionPassed(opcode))
1062 {
1063 uint32_t Rd; // the destination register
1064 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1065 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1066 bool setflags;
1067 switch (encoding) {
1068 case eEncodingT1:
1069 Rd = Bits32(opcode, 11, 8);
1070 setflags = BitIsSet(opcode, 20);
1071 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1072 break;
1073 case eEncodingA1:
1074 Rd = Bits32(opcode, 15, 12);
1075 setflags = BitIsSet(opcode, 20);
1076 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
1077
1078 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1079 if (Rd == 15 && setflags)
1080 return EmulateSUBSPcLrEtc (opcode, encoding);
1081 break;
1082 default:
1083 return false;
1084 }
1085 uint32_t result = ~imm32;
1086
1087 // The context specifies that an immediate is to be moved into Rd.
1088 EmulateInstruction::Context context;
1089 context.type = EmulateInstruction::eContextImmediate;
1090 context.SetNoArgs ();
1091
1092 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1093 return false;
1094 }
1095 return true;
1096 }
1097
1098 // Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1099 // It can optionally update the condition flags based on the result.
1100 bool
EmulateMVNReg(const uint32_t opcode,const ARMEncoding encoding)1101 EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
1102 {
1103 #if 0
1104 // ARM pseudo code...
1105 if (ConditionPassed())
1106 {
1107 EncodingSpecificOperations();
1108 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1109 result = NOT(shifted);
1110 if d == 15 then // Can only occur for ARM encoding
1111 ALUWritePC(result); // setflags is always FALSE here
1112 else
1113 R[d] = result;
1114 if setflags then
1115 APSR.N = result<31>;
1116 APSR.Z = IsZeroBit(result);
1117 APSR.C = carry;
1118 // APSR.V unchanged
1119 }
1120 #endif
1121
1122 if (ConditionPassed(opcode))
1123 {
1124 uint32_t Rm; // the source register
1125 uint32_t Rd; // the destination register
1126 ARM_ShifterType shift_t;
1127 uint32_t shift_n; // the shift applied to the value read from Rm
1128 bool setflags;
1129 uint32_t carry; // the carry bit after the shift operation
1130 switch (encoding) {
1131 case eEncodingT1:
1132 Rd = Bits32(opcode, 2, 0);
1133 Rm = Bits32(opcode, 5, 3);
1134 setflags = !InITBlock();
1135 shift_t = SRType_LSL;
1136 shift_n = 0;
1137 if (InITBlock())
1138 return false;
1139 break;
1140 case eEncodingT2:
1141 Rd = Bits32(opcode, 11, 8);
1142 Rm = Bits32(opcode, 3, 0);
1143 setflags = BitIsSet(opcode, 20);
1144 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1145 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1146 if (BadReg(Rd) || BadReg(Rm))
1147 return false;
1148 break;
1149 case eEncodingA1:
1150 Rd = Bits32(opcode, 15, 12);
1151 Rm = Bits32(opcode, 3, 0);
1152 setflags = BitIsSet(opcode, 20);
1153 shift_n = DecodeImmShiftARM(opcode, shift_t);
1154 break;
1155 default:
1156 return false;
1157 }
1158 bool success = false;
1159 uint32_t value = ReadCoreReg(Rm, &success);
1160 if (!success)
1161 return false;
1162
1163 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1164 if (!success)
1165 return false;
1166 uint32_t result = ~shifted;
1167
1168 // The context specifies that an immediate is to be moved into Rd.
1169 EmulateInstruction::Context context;
1170 context.type = EmulateInstruction::eContextImmediate;
1171 context.SetNoArgs ();
1172
1173 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1174 return false;
1175 }
1176 return true;
1177 }
1178
1179 // PC relative immediate load into register, possibly followed by ADD (SP plus register).
1180 // LDR (literal)
1181 bool
EmulateLDRRtPCRelative(const uint32_t opcode,const ARMEncoding encoding)1182 EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
1183 {
1184 #if 0
1185 // ARM pseudo code...
1186 if (ConditionPassed())
1187 {
1188 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1189 base = Align(PC,4);
1190 address = if add then (base + imm32) else (base - imm32);
1191 data = MemU[address,4];
1192 if t == 15 then
1193 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1194 elsif UnalignedSupport() || address<1:0> = '00' then
1195 R[t] = data;
1196 else // Can only apply before ARMv7
1197 if CurrentInstrSet() == InstrSet_ARM then
1198 R[t] = ROR(data, 8*UInt(address<1:0>));
1199 else
1200 R[t] = bits(32) UNKNOWN;
1201 }
1202 #endif
1203
1204 if (ConditionPassed(opcode))
1205 {
1206 bool success = false;
1207 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1208 if (!success)
1209 return false;
1210
1211 // PC relative immediate load context
1212 EmulateInstruction::Context context;
1213 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1214 RegisterInfo pc_reg;
1215 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
1216 context.SetRegisterPlusOffset (pc_reg, 0);
1217
1218 uint32_t Rt; // the destination register
1219 uint32_t imm32; // immediate offset from the PC
1220 bool add; // +imm32 or -imm32?
1221 addr_t base; // the base address
1222 addr_t address; // the PC relative address
1223 uint32_t data; // the literal data value from the PC relative load
1224 switch (encoding) {
1225 case eEncodingT1:
1226 Rt = Bits32(opcode, 10, 8);
1227 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1228 add = true;
1229 break;
1230 case eEncodingT2:
1231 Rt = Bits32(opcode, 15, 12);
1232 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1233 add = BitIsSet(opcode, 23);
1234 if (Rt == 15 && InITBlock() && !LastInITBlock())
1235 return false;
1236 break;
1237 default:
1238 return false;
1239 }
1240
1241 base = Align(pc, 4);
1242 if (add)
1243 address = base + imm32;
1244 else
1245 address = base - imm32;
1246
1247 context.SetRegisterPlusOffset(pc_reg, address - base);
1248 data = MemURead(context, address, 4, 0, &success);
1249 if (!success)
1250 return false;
1251
1252 if (Rt == 15)
1253 {
1254 if (Bits32(address, 1, 0) == 0)
1255 {
1256 // In ARMv5T and above, this is an interworking branch.
1257 if (!LoadWritePC(context, data))
1258 return false;
1259 }
1260 else
1261 return false;
1262 }
1263 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1264 {
1265 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1266 return false;
1267 }
1268 else // We don't handle ARM for now.
1269 return false;
1270
1271 }
1272 return true;
1273 }
1274
1275 // An add operation to adjust the SP.
1276 // ADD (SP plus immediate)
1277 bool
EmulateADDSPImm(const uint32_t opcode,const ARMEncoding encoding)1278 EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
1279 {
1280 #if 0
1281 // ARM pseudo code...
1282 if (ConditionPassed())
1283 {
1284 EncodingSpecificOperations();
1285 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1286 if d == 15 then // Can only occur for ARM encoding
1287 ALUWritePC(result); // setflags is always FALSE here
1288 else
1289 R[d] = result;
1290 if setflags then
1291 APSR.N = result<31>;
1292 APSR.Z = IsZeroBit(result);
1293 APSR.C = carry;
1294 APSR.V = overflow;
1295 }
1296 #endif
1297
1298 bool success = false;
1299
1300 if (ConditionPassed(opcode))
1301 {
1302 const addr_t sp = ReadCoreReg (SP_REG, &success);
1303 if (!success)
1304 return false;
1305 uint32_t imm32; // the immediate operand
1306 uint32_t d;
1307 //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1
1308 switch (encoding)
1309 {
1310 case eEncodingT1:
1311 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1312 d = Bits32 (opcode, 10, 8);
1313 imm32 = (Bits32 (opcode, 7, 0) << 2);
1314
1315 break;
1316
1317 case eEncodingT2:
1318 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1319 d = 13;
1320 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1321
1322 break;
1323
1324 default:
1325 return false;
1326 }
1327 addr_t sp_offset = imm32;
1328 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1329
1330 EmulateInstruction::Context context;
1331 context.type = EmulateInstruction::eContextAdjustStackPointer;
1332 RegisterInfo sp_reg;
1333 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1334 context.SetRegisterPlusOffset (sp_reg, sp_offset);
1335
1336 if (d == 15)
1337 {
1338 if (!ALUWritePC (context, addr))
1339 return false;
1340 }
1341 else
1342 {
1343 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1344 return false;
1345
1346 // Add this back if/when support eEncodingT3 eEncodingA1
1347 //if (setflags)
1348 //{
1349 // APSR.N = result<31>;
1350 // APSR.Z = IsZeroBit(result);
1351 // APSR.C = carry;
1352 // APSR.V = overflow;
1353 //}
1354 }
1355 }
1356 return true;
1357 }
1358
1359 // An add operation to adjust the SP.
1360 // ADD (SP plus register)
1361 bool
EmulateADDSPRm(const uint32_t opcode,const ARMEncoding encoding)1362 EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
1363 {
1364 #if 0
1365 // ARM pseudo code...
1366 if (ConditionPassed())
1367 {
1368 EncodingSpecificOperations();
1369 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1370 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1371 if d == 15 then
1372 ALUWritePC(result); // setflags is always FALSE here
1373 else
1374 R[d] = result;
1375 if setflags then
1376 APSR.N = result<31>;
1377 APSR.Z = IsZeroBit(result);
1378 APSR.C = carry;
1379 APSR.V = overflow;
1380 }
1381 #endif
1382
1383 bool success = false;
1384
1385 if (ConditionPassed(opcode))
1386 {
1387 const addr_t sp = ReadCoreReg (SP_REG, &success);
1388 if (!success)
1389 return false;
1390 uint32_t Rm; // the second operand
1391 switch (encoding) {
1392 case eEncodingT2:
1393 Rm = Bits32(opcode, 6, 3);
1394 break;
1395 default:
1396 return false;
1397 }
1398 int32_t reg_value = ReadCoreReg(Rm, &success);
1399 if (!success)
1400 return false;
1401
1402 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1403
1404 EmulateInstruction::Context context;
1405 context.type = eContextArithmetic;
1406 RegisterInfo sp_reg;
1407 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1408
1409 RegisterInfo other_reg;
1410 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
1411 context.SetRegisterRegisterOperands (sp_reg, other_reg);
1412
1413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
1414 return false;
1415 }
1416 return true;
1417 }
1418
1419 // Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1420 // at a PC-relative address, and changes instruction set from ARM to Thumb, or
1421 // from Thumb to ARM.
1422 // BLX (immediate)
1423 bool
EmulateBLXImmediate(const uint32_t opcode,const ARMEncoding encoding)1424 EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
1425 {
1426 #if 0
1427 // ARM pseudo code...
1428 if (ConditionPassed())
1429 {
1430 EncodingSpecificOperations();
1431 if CurrentInstrSet() == InstrSet_ARM then
1432 LR = PC - 4;
1433 else
1434 LR = PC<31:1> : '1';
1435 if targetInstrSet == InstrSet_ARM then
1436 targetAddress = Align(PC,4) + imm32;
1437 else
1438 targetAddress = PC + imm32;
1439 SelectInstrSet(targetInstrSet);
1440 BranchWritePC(targetAddress);
1441 }
1442 #endif
1443
1444 bool success = true;
1445
1446 if (ConditionPassed(opcode))
1447 {
1448 EmulateInstruction::Context context;
1449 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1450 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1451 if (!success)
1452 return false;
1453 addr_t lr; // next instruction address
1454 addr_t target; // target address
1455 int32_t imm32; // PC-relative offset
1456 switch (encoding) {
1457 case eEncodingT1:
1458 {
1459 lr = pc | 1u; // return address
1460 uint32_t S = Bit32(opcode, 26);
1461 uint32_t imm10 = Bits32(opcode, 25, 16);
1462 uint32_t J1 = Bit32(opcode, 13);
1463 uint32_t J2 = Bit32(opcode, 11);
1464 uint32_t imm11 = Bits32(opcode, 10, 0);
1465 uint32_t I1 = !(J1 ^ S);
1466 uint32_t I2 = !(J2 ^ S);
1467 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
1468 imm32 = llvm::SignExtend32<25>(imm25);
1469 target = pc + imm32;
1470 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
1471 if (InITBlock() && !LastInITBlock())
1472 return false;
1473 break;
1474 }
1475 case eEncodingT2:
1476 {
1477 lr = pc | 1u; // return address
1478 uint32_t S = Bit32(opcode, 26);
1479 uint32_t imm10H = Bits32(opcode, 25, 16);
1480 uint32_t J1 = Bit32(opcode, 13);
1481 uint32_t J2 = Bit32(opcode, 11);
1482 uint32_t imm10L = Bits32(opcode, 10, 1);
1483 uint32_t I1 = !(J1 ^ S);
1484 uint32_t I2 = !(J2 ^ S);
1485 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
1486 imm32 = llvm::SignExtend32<25>(imm25);
1487 target = Align(pc, 4) + imm32;
1488 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
1489 if (InITBlock() && !LastInITBlock())
1490 return false;
1491 break;
1492 }
1493 case eEncodingA1:
1494 lr = pc - 4; // return address
1495 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1496 target = Align(pc, 4) + imm32;
1497 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
1498 break;
1499 case eEncodingA2:
1500 lr = pc - 4; // return address
1501 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1502 target = pc + imm32;
1503 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
1504 break;
1505 default:
1506 return false;
1507 }
1508 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1509 return false;
1510 if (!BranchWritePC(context, target))
1511 return false;
1512 }
1513 return true;
1514 }
1515
1516 // Branch with Link and Exchange (register) calls a subroutine at an address and
1517 // instruction set specified by a register.
1518 // BLX (register)
1519 bool
EmulateBLXRm(const uint32_t opcode,const ARMEncoding encoding)1520 EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
1521 {
1522 #if 0
1523 // ARM pseudo code...
1524 if (ConditionPassed())
1525 {
1526 EncodingSpecificOperations();
1527 target = R[m];
1528 if CurrentInstrSet() == InstrSet_ARM then
1529 next_instr_addr = PC - 4;
1530 LR = next_instr_addr;
1531 else
1532 next_instr_addr = PC - 2;
1533 LR = next_instr_addr<31:1> : '1';
1534 BXWritePC(target);
1535 }
1536 #endif
1537
1538 bool success = false;
1539
1540 if (ConditionPassed(opcode))
1541 {
1542 EmulateInstruction::Context context;
1543 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1544 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1545 addr_t lr; // next instruction address
1546 if (!success)
1547 return false;
1548 uint32_t Rm; // the register with the target address
1549 switch (encoding) {
1550 case eEncodingT1:
1551 lr = (pc - 2) | 1u; // return address
1552 Rm = Bits32(opcode, 6, 3);
1553 // if m == 15 then UNPREDICTABLE;
1554 if (Rm == 15)
1555 return false;
1556 if (InITBlock() && !LastInITBlock())
1557 return false;
1558 break;
1559 case eEncodingA1:
1560 lr = pc - 4; // return address
1561 Rm = Bits32(opcode, 3, 0);
1562 // if m == 15 then UNPREDICTABLE;
1563 if (Rm == 15)
1564 return false;
1565 break;
1566 default:
1567 return false;
1568 }
1569 addr_t target = ReadCoreReg (Rm, &success);
1570 if (!success)
1571 return false;
1572 RegisterInfo dwarf_reg;
1573 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1574 context.SetRegister (dwarf_reg);
1575 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1576 return false;
1577 if (!BXWritePC(context, target))
1578 return false;
1579 }
1580 return true;
1581 }
1582
1583 // Branch and Exchange causes a branch to an address and instruction set specified by a register.
1584 bool
EmulateBXRm(const uint32_t opcode,const ARMEncoding encoding)1585 EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
1586 {
1587 #if 0
1588 // ARM pseudo code...
1589 if (ConditionPassed())
1590 {
1591 EncodingSpecificOperations();
1592 BXWritePC(R[m]);
1593 }
1594 #endif
1595
1596 if (ConditionPassed(opcode))
1597 {
1598 EmulateInstruction::Context context;
1599 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1600 uint32_t Rm; // the register with the target address
1601 switch (encoding) {
1602 case eEncodingT1:
1603 Rm = Bits32(opcode, 6, 3);
1604 if (InITBlock() && !LastInITBlock())
1605 return false;
1606 break;
1607 case eEncodingA1:
1608 Rm = Bits32(opcode, 3, 0);
1609 break;
1610 default:
1611 return false;
1612 }
1613 bool success = false;
1614 addr_t target = ReadCoreReg (Rm, &success);
1615 if (!success)
1616 return false;
1617
1618 RegisterInfo dwarf_reg;
1619 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1620 context.SetRegister (dwarf_reg);
1621 if (!BXWritePC(context, target))
1622 return false;
1623 }
1624 return true;
1625 }
1626
1627 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1628 // address and instruction set specified by a register as though it were a BX instruction.
1629 //
1630 // TODO: Emulate Jazelle architecture?
1631 // We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1632 bool
EmulateBXJRm(const uint32_t opcode,const ARMEncoding encoding)1633 EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
1634 {
1635 #if 0
1636 // ARM pseudo code...
1637 if (ConditionPassed())
1638 {
1639 EncodingSpecificOperations();
1640 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
1641 BXWritePC(R[m]);
1642 else
1643 if JazelleAcceptsExecution() then
1644 SwitchToJazelleExecution();
1645 else
1646 SUBARCHITECTURE_DEFINED handler call;
1647 }
1648 #endif
1649
1650 if (ConditionPassed(opcode))
1651 {
1652 EmulateInstruction::Context context;
1653 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1654 uint32_t Rm; // the register with the target address
1655 switch (encoding) {
1656 case eEncodingT1:
1657 Rm = Bits32(opcode, 19, 16);
1658 if (BadReg(Rm))
1659 return false;
1660 if (InITBlock() && !LastInITBlock())
1661 return false;
1662 break;
1663 case eEncodingA1:
1664 Rm = Bits32(opcode, 3, 0);
1665 if (Rm == 15)
1666 return false;
1667 break;
1668 default:
1669 return false;
1670 }
1671 bool success = false;
1672 addr_t target = ReadCoreReg (Rm, &success);
1673 if (!success)
1674 return false;
1675
1676 RegisterInfo dwarf_reg;
1677 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
1678 context.SetRegister (dwarf_reg);
1679 if (!BXWritePC(context, target))
1680 return false;
1681 }
1682 return true;
1683 }
1684
1685 // Set r7 to point to some ip offset.
1686 // SUB (immediate)
1687 bool
EmulateSUBR7IPImm(const uint32_t opcode,const ARMEncoding encoding)1688 EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
1689 {
1690 #if 0
1691 // ARM pseudo code...
1692 if (ConditionPassed())
1693 {
1694 EncodingSpecificOperations();
1695 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1696 if d == 15 then // Can only occur for ARM encoding
1697 ALUWritePC(result); // setflags is always FALSE here
1698 else
1699 R[d] = result;
1700 if setflags then
1701 APSR.N = result<31>;
1702 APSR.Z = IsZeroBit(result);
1703 APSR.C = carry;
1704 APSR.V = overflow;
1705 }
1706 #endif
1707
1708 if (ConditionPassed(opcode))
1709 {
1710 bool success = false;
1711 const addr_t ip = ReadCoreReg (12, &success);
1712 if (!success)
1713 return false;
1714 uint32_t imm32;
1715 switch (encoding) {
1716 case eEncodingA1:
1717 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1718 break;
1719 default:
1720 return false;
1721 }
1722 addr_t ip_offset = imm32;
1723 addr_t addr = ip - ip_offset; // the adjusted ip value
1724
1725 EmulateInstruction::Context context;
1726 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1727 RegisterInfo dwarf_reg;
1728 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
1729 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
1730
1731 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
1732 return false;
1733 }
1734 return true;
1735 }
1736
1737 // Set ip to point to some stack offset.
1738 // SUB (SP minus immediate)
1739 bool
EmulateSUBIPSPImm(const uint32_t opcode,const ARMEncoding encoding)1740 EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
1741 {
1742 #if 0
1743 // ARM pseudo code...
1744 if (ConditionPassed())
1745 {
1746 EncodingSpecificOperations();
1747 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1748 if d == 15 then // Can only occur for ARM encoding
1749 ALUWritePC(result); // setflags is always FALSE here
1750 else
1751 R[d] = result;
1752 if setflags then
1753 APSR.N = result<31>;
1754 APSR.Z = IsZeroBit(result);
1755 APSR.C = carry;
1756 APSR.V = overflow;
1757 }
1758 #endif
1759
1760 if (ConditionPassed(opcode))
1761 {
1762 bool success = false;
1763 const addr_t sp = ReadCoreReg (SP_REG, &success);
1764 if (!success)
1765 return false;
1766 uint32_t imm32;
1767 switch (encoding) {
1768 case eEncodingA1:
1769 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1770 break;
1771 default:
1772 return false;
1773 }
1774 addr_t sp_offset = imm32;
1775 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1776
1777 EmulateInstruction::Context context;
1778 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1779 RegisterInfo dwarf_reg;
1780 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
1781 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
1782
1783 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
1784 return false;
1785 }
1786 return true;
1787 }
1788
1789 // This instruction subtracts an immediate value from the SP value, and writes
1790 // the result to the destination register.
1791 //
1792 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
1793 bool
EmulateSUBSPImm(const uint32_t opcode,const ARMEncoding encoding)1794 EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
1795 {
1796 #if 0
1797 // ARM pseudo code...
1798 if (ConditionPassed())
1799 {
1800 EncodingSpecificOperations();
1801 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
1802 if d == 15 then // Can only occur for ARM encoding
1803 ALUWritePC(result); // setflags is always FALSE here
1804 else
1805 R[d] = result;
1806 if setflags then
1807 APSR.N = result<31>;
1808 APSR.Z = IsZeroBit(result);
1809 APSR.C = carry;
1810 APSR.V = overflow;
1811 }
1812 #endif
1813
1814 bool success = false;
1815 if (ConditionPassed(opcode))
1816 {
1817 const addr_t sp = ReadCoreReg (SP_REG, &success);
1818 if (!success)
1819 return false;
1820
1821 uint32_t Rd;
1822 bool setflags;
1823 uint32_t imm32;
1824 switch (encoding) {
1825 case eEncodingT1:
1826 Rd = 13;
1827 setflags = false;
1828 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1829 break;
1830 case eEncodingT2:
1831 Rd = Bits32(opcode, 11, 8);
1832 setflags = BitIsSet(opcode, 20);
1833 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1834 if (Rd == 15 && setflags)
1835 return EmulateCMPImm(opcode, eEncodingT2);
1836 if (Rd == 15 && !setflags)
1837 return false;
1838 break;
1839 case eEncodingT3:
1840 Rd = Bits32(opcode, 11, 8);
1841 setflags = false;
1842 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
1843 if (Rd == 15)
1844 return false;
1845 break;
1846 case eEncodingA1:
1847 Rd = Bits32(opcode, 15, 12);
1848 setflags = BitIsSet(opcode, 20);
1849 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1850
1851 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1852 if (Rd == 15 && setflags)
1853 return EmulateSUBSPcLrEtc (opcode, encoding);
1854 break;
1855 default:
1856 return false;
1857 }
1858 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1859
1860 EmulateInstruction::Context context;
1861 if (Rd == 13)
1862 {
1863 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1864 // value gets passed down to context.SetImmediateSigned.
1865 context.type = EmulateInstruction::eContextAdjustStackPointer;
1866 context.SetImmediateSigned (-imm64); // the stack pointer offset
1867 }
1868 else
1869 {
1870 context.type = EmulateInstruction::eContextImmediate;
1871 context.SetNoArgs ();
1872 }
1873
1874 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
1875 return false;
1876 }
1877 return true;
1878 }
1879
1880 // A store operation to the stack that also updates the SP.
1881 bool
EmulateSTRRtSP(const uint32_t opcode,const ARMEncoding encoding)1882 EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
1883 {
1884 #if 0
1885 // ARM pseudo code...
1886 if (ConditionPassed())
1887 {
1888 EncodingSpecificOperations();
1889 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1890 address = if index then offset_addr else R[n];
1891 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1892 if wback then R[n] = offset_addr;
1893 }
1894 #endif
1895
1896 bool conditional = false;
1897 bool success = false;
1898 if (ConditionPassed(opcode, &conditional))
1899 {
1900 const uint32_t addr_byte_size = GetAddressByteSize();
1901 const addr_t sp = ReadCoreReg (SP_REG, &success);
1902 if (!success)
1903 return false;
1904 uint32_t Rt; // the source register
1905 uint32_t imm12;
1906 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1907
1908 bool index;
1909 bool add;
1910 bool wback;
1911 switch (encoding) {
1912 case eEncodingA1:
1913 Rt = Bits32(opcode, 15, 12);
1914 imm12 = Bits32(opcode, 11, 0);
1915 Rn = Bits32 (opcode, 19, 16);
1916
1917 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1918 return false;
1919
1920 index = BitIsSet (opcode, 24);
1921 add = BitIsSet (opcode, 23);
1922 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1923
1924 if (wback && ((Rn == 15) || (Rn == Rt)))
1925 return false;
1926 break;
1927 default:
1928 return false;
1929 }
1930 addr_t offset_addr;
1931 if (add)
1932 offset_addr = sp + imm12;
1933 else
1934 offset_addr = sp - imm12;
1935
1936 addr_t addr;
1937 if (index)
1938 addr = offset_addr;
1939 else
1940 addr = sp;
1941
1942 EmulateInstruction::Context context;
1943 if (conditional)
1944 context.type = EmulateInstruction::eContextRegisterStore;
1945 else
1946 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1947 RegisterInfo sp_reg;
1948 RegisterInfo dwarf_reg;
1949
1950 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1951 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1952 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
1953 if (Rt != 15)
1954 {
1955 uint32_t reg_value = ReadCoreReg(Rt, &success);
1956 if (!success)
1957 return false;
1958 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
1959 return false;
1960 }
1961 else
1962 {
1963 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1964 if (!success)
1965 return false;
1966 if (!MemUWrite (context, addr, pc, addr_byte_size))
1967 return false;
1968 }
1969
1970
1971 if (wback)
1972 {
1973 context.type = EmulateInstruction::eContextAdjustStackPointer;
1974 context.SetImmediateSigned (addr - sp);
1975 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1976 return false;
1977 }
1978 }
1979 return true;
1980 }
1981
1982 // Vector Push stores multiple extension registers to the stack.
1983 // It also updates SP to point to the start of the stored data.
1984 bool
EmulateVPUSH(const uint32_t opcode,const ARMEncoding encoding)1985 EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
1986 {
1987 #if 0
1988 // ARM pseudo code...
1989 if (ConditionPassed())
1990 {
1991 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1992 address = SP - imm32;
1993 SP = SP - imm32;
1994 if single_regs then
1995 for r = 0 to regs-1
1996 MemA[address,4] = S[d+r]; address = address+4;
1997 else
1998 for r = 0 to regs-1
1999 // Store as two word-aligned words in the correct order for current endianness.
2000 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2001 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2002 address = address+8;
2003 }
2004 #endif
2005
2006 bool success = false;
2007 bool conditional = false;
2008 if (ConditionPassed(opcode, &conditional))
2009 {
2010 const uint32_t addr_byte_size = GetAddressByteSize();
2011 const addr_t sp = ReadCoreReg (SP_REG, &success);
2012 if (!success)
2013 return false;
2014 bool single_regs;
2015 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2016 uint32_t imm32; // stack offset
2017 uint32_t regs; // number of registers
2018 switch (encoding) {
2019 case eEncodingT1:
2020 case eEncodingA1:
2021 single_regs = false;
2022 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2023 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2024 // If UInt(imm8) is odd, see "FSTMX".
2025 regs = Bits32(opcode, 7, 0) / 2;
2026 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2027 if (regs == 0 || regs > 16 || (d + regs) > 32)
2028 return false;
2029 break;
2030 case eEncodingT2:
2031 case eEncodingA2:
2032 single_regs = true;
2033 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2034 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2035 regs = Bits32(opcode, 7, 0);
2036 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2037 if (regs == 0 || regs > 16 || (d + regs) > 32)
2038 return false;
2039 break;
2040 default:
2041 return false;
2042 }
2043 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2044 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2045 addr_t sp_offset = imm32;
2046 addr_t addr = sp - sp_offset;
2047 uint32_t i;
2048
2049 EmulateInstruction::Context context;
2050 if (conditional)
2051 context.type = EmulateInstruction::eContextRegisterStore;
2052 else
2053 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2054 RegisterInfo dwarf_reg;
2055 RegisterInfo sp_reg;
2056 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
2057 for (i=0; i<regs; ++i)
2058 {
2059 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2060 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
2061 // uint64_t to accommodate 64-bit registers.
2062 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
2063 if (!success)
2064 return false;
2065 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
2066 return false;
2067 addr += reg_byte_size;
2068 }
2069
2070 context.type = EmulateInstruction::eContextAdjustStackPointer;
2071 context.SetImmediateSigned (-sp_offset);
2072
2073 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2074 return false;
2075 }
2076 return true;
2077 }
2078
2079 // Vector Pop loads multiple extension registers from the stack.
2080 // It also updates SP to point just above the loaded data.
2081 bool
EmulateVPOP(const uint32_t opcode,const ARMEncoding encoding)2082 EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
2083 {
2084 #if 0
2085 // ARM pseudo code...
2086 if (ConditionPassed())
2087 {
2088 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2089 address = SP;
2090 SP = SP + imm32;
2091 if single_regs then
2092 for r = 0 to regs-1
2093 S[d+r] = MemA[address,4]; address = address+4;
2094 else
2095 for r = 0 to regs-1
2096 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2097 // Combine the word-aligned words in the correct order for current endianness.
2098 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2099 }
2100 #endif
2101
2102 bool success = false;
2103 bool conditional = false;
2104 if (ConditionPassed(opcode, &conditional))
2105 {
2106 const uint32_t addr_byte_size = GetAddressByteSize();
2107 const addr_t sp = ReadCoreReg (SP_REG, &success);
2108 if (!success)
2109 return false;
2110 bool single_regs;
2111 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2112 uint32_t imm32; // stack offset
2113 uint32_t regs; // number of registers
2114 switch (encoding) {
2115 case eEncodingT1:
2116 case eEncodingA1:
2117 single_regs = false;
2118 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2119 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2120 // If UInt(imm8) is odd, see "FLDMX".
2121 regs = Bits32(opcode, 7, 0) / 2;
2122 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2123 if (regs == 0 || regs > 16 || (d + regs) > 32)
2124 return false;
2125 break;
2126 case eEncodingT2:
2127 case eEncodingA2:
2128 single_regs = true;
2129 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2130 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2131 regs = Bits32(opcode, 7, 0);
2132 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2133 if (regs == 0 || regs > 16 || (d + regs) > 32)
2134 return false;
2135 break;
2136 default:
2137 return false;
2138 }
2139 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2140 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2141 addr_t sp_offset = imm32;
2142 addr_t addr = sp;
2143 uint32_t i;
2144 uint64_t data; // uint64_t to accomodate 64-bit registers.
2145
2146 EmulateInstruction::Context context;
2147 if (conditional)
2148 context.type = EmulateInstruction::eContextRegisterLoad;
2149 else
2150 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2151 RegisterInfo dwarf_reg;
2152 RegisterInfo sp_reg;
2153 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
2154 for (i=0; i<regs; ++i)
2155 {
2156 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
2157 context.SetRegisterPlusOffset (sp_reg, addr - sp);
2158 data = MemARead(context, addr, reg_byte_size, 0, &success);
2159 if (!success)
2160 return false;
2161 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
2162 return false;
2163 addr += reg_byte_size;
2164 }
2165
2166 context.type = EmulateInstruction::eContextAdjustStackPointer;
2167 context.SetImmediateSigned (sp_offset);
2168
2169 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2170 return false;
2171 }
2172 return true;
2173 }
2174
2175 // SVC (previously SWI)
2176 bool
EmulateSVC(const uint32_t opcode,const ARMEncoding encoding)2177 EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
2178 {
2179 #if 0
2180 // ARM pseudo code...
2181 if (ConditionPassed())
2182 {
2183 EncodingSpecificOperations();
2184 CallSupervisor();
2185 }
2186 #endif
2187
2188 bool success = false;
2189
2190 if (ConditionPassed(opcode))
2191 {
2192 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2193 addr_t lr; // next instruction address
2194 if (!success)
2195 return false;
2196 uint32_t imm32; // the immediate constant
2197 uint32_t mode; // ARM or Thumb mode
2198 switch (encoding) {
2199 case eEncodingT1:
2200 lr = (pc + 2) | 1u; // return address
2201 imm32 = Bits32(opcode, 7, 0);
2202 mode = eModeThumb;
2203 break;
2204 case eEncodingA1:
2205 lr = pc + 4; // return address
2206 imm32 = Bits32(opcode, 23, 0);
2207 mode = eModeARM;
2208 break;
2209 default:
2210 return false;
2211 }
2212
2213 EmulateInstruction::Context context;
2214 context.type = EmulateInstruction::eContextSupervisorCall;
2215 context.SetISAAndImmediate (mode, imm32);
2216 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2217 return false;
2218 }
2219 return true;
2220 }
2221
2222 // If Then makes up to four following instructions (the IT block) conditional.
2223 bool
EmulateIT(const uint32_t opcode,const ARMEncoding encoding)2224 EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
2225 {
2226 #if 0
2227 // ARM pseudo code...
2228 EncodingSpecificOperations();
2229 ITSTATE.IT<7:0> = firstcond:mask;
2230 #endif
2231
2232 m_it_session.InitIT(Bits32(opcode, 7, 0));
2233 return true;
2234 }
2235
2236 bool
EmulateNop(const uint32_t opcode,const ARMEncoding encoding)2237 EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2238 {
2239 // NOP, nothing to do...
2240 return true;
2241 }
2242
2243 // Branch causes a branch to a target address.
2244 bool
EmulateB(const uint32_t opcode,const ARMEncoding encoding)2245 EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
2246 {
2247 #if 0
2248 // ARM pseudo code...
2249 if (ConditionPassed())
2250 {
2251 EncodingSpecificOperations();
2252 BranchWritePC(PC + imm32);
2253 }
2254 #endif
2255
2256 bool success = false;
2257
2258 if (ConditionPassed(opcode))
2259 {
2260 EmulateInstruction::Context context;
2261 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2262 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2263 if (!success)
2264 return false;
2265 addr_t target; // target address
2266 int32_t imm32; // PC-relative offset
2267 switch (encoding) {
2268 case eEncodingT1:
2269 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2270 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2271 target = pc + imm32;
2272 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2273 break;
2274 case eEncodingT2:
2275 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
2276 target = pc + imm32;
2277 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2278 break;
2279 case eEncodingT3:
2280 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2281 {
2282 uint32_t S = Bit32(opcode, 26);
2283 uint32_t imm6 = Bits32(opcode, 21, 16);
2284 uint32_t J1 = Bit32(opcode, 13);
2285 uint32_t J2 = Bit32(opcode, 11);
2286 uint32_t imm11 = Bits32(opcode, 10, 0);
2287 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2288 imm32 = llvm::SignExtend32<21>(imm21);
2289 target = pc + imm32;
2290 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2291 break;
2292 }
2293 case eEncodingT4:
2294 {
2295 uint32_t S = Bit32(opcode, 26);
2296 uint32_t imm10 = Bits32(opcode, 25, 16);
2297 uint32_t J1 = Bit32(opcode, 13);
2298 uint32_t J2 = Bit32(opcode, 11);
2299 uint32_t imm11 = Bits32(opcode, 10, 0);
2300 uint32_t I1 = !(J1 ^ S);
2301 uint32_t I2 = !(J2 ^ S);
2302 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2303 imm32 = llvm::SignExtend32<25>(imm25);
2304 target = pc + imm32;
2305 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2306 break;
2307 }
2308 case eEncodingA1:
2309 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2310 target = pc + imm32;
2311 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
2312 break;
2313 default:
2314 return false;
2315 }
2316 if (!BranchWritePC(context, target))
2317 return false;
2318 }
2319 return true;
2320 }
2321
2322 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2323 // zero and conditionally branch forward a constant value. They do not affect the condition flags.
2324 // CBNZ, CBZ
2325 bool
EmulateCB(const uint32_t opcode,const ARMEncoding encoding)2326 EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
2327 {
2328 #if 0
2329 // ARM pseudo code...
2330 EncodingSpecificOperations();
2331 if nonzero ^ IsZero(R[n]) then
2332 BranchWritePC(PC + imm32);
2333 #endif
2334
2335 bool success = false;
2336
2337 // Read the register value from the operand register Rn.
2338 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2339 if (!success)
2340 return false;
2341
2342 EmulateInstruction::Context context;
2343 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2344 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2345 if (!success)
2346 return false;
2347
2348 addr_t target; // target address
2349 uint32_t imm32; // PC-relative offset to branch forward
2350 bool nonzero;
2351 switch (encoding) {
2352 case eEncodingT1:
2353 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2354 nonzero = BitIsSet(opcode, 11);
2355 target = pc + imm32;
2356 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
2357 break;
2358 default:
2359 return false;
2360 }
2361 if (nonzero ^ (reg_val == 0))
2362 if (!BranchWritePC(context, target))
2363 return false;
2364
2365 return true;
2366 }
2367
2368 // Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2369 // A base register provides a pointer to the table, and a second register supplies an index into the table.
2370 // The branch length is twice the value of the byte returned from the table.
2371 //
2372 // Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2373 // A base register provides a pointer to the table, and a second register supplies an index into the table.
2374 // The branch length is twice the value of the halfword returned from the table.
2375 // TBB, TBH
2376 bool
EmulateTB(const uint32_t opcode,const ARMEncoding encoding)2377 EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
2378 {
2379 #if 0
2380 // ARM pseudo code...
2381 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2382 if is_tbh then
2383 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2384 else
2385 halfwords = UInt(MemU[R[n]+R[m], 1]);
2386 BranchWritePC(PC + 2*halfwords);
2387 #endif
2388
2389 bool success = false;
2390
2391 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2392 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2393 bool is_tbh; // true if table branch halfword
2394 switch (encoding) {
2395 case eEncodingT1:
2396 Rn = Bits32(opcode, 19, 16);
2397 Rm = Bits32(opcode, 3, 0);
2398 is_tbh = BitIsSet(opcode, 4);
2399 if (Rn == 13 || BadReg(Rm))
2400 return false;
2401 if (InITBlock() && !LastInITBlock())
2402 return false;
2403 break;
2404 default:
2405 return false;
2406 }
2407
2408 // Read the address of the table from the operand register Rn.
2409 // The PC can be used, in which case the table immediately follows this instruction.
2410 uint32_t base = ReadCoreReg(Rm, &success);
2411 if (!success)
2412 return false;
2413
2414 // the table index
2415 uint32_t index = ReadCoreReg(Rm, &success);
2416 if (!success)
2417 return false;
2418
2419 // the offsetted table address
2420 addr_t addr = base + (is_tbh ? index*2 : index);
2421
2422 // PC-relative offset to branch forward
2423 EmulateInstruction::Context context;
2424 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2425 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2426 if (!success)
2427 return false;
2428
2429 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2430 if (!success)
2431 return false;
2432
2433 // target address
2434 addr_t target = pc + offset;
2435 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2436 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
2437
2438 if (!BranchWritePC(context, target))
2439 return false;
2440
2441 return true;
2442 }
2443
2444 // This instruction adds an immediate value to a register value, and writes the result to the destination register.
2445 // It can optionally update the condition flags based on the result.
2446 bool
EmulateADDImmThumb(const uint32_t opcode,const ARMEncoding encoding)2447 EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
2448 {
2449 #if 0
2450 if ConditionPassed() then
2451 EncodingSpecificOperations();
2452 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2453 R[d] = result;
2454 if setflags then
2455 APSR.N = result<31>;
2456 APSR.Z = IsZeroBit(result);
2457 APSR.C = carry;
2458 APSR.V = overflow;
2459 #endif
2460
2461 bool success = false;
2462
2463 if (ConditionPassed(opcode))
2464 {
2465 uint32_t d;
2466 uint32_t n;
2467 bool setflags;
2468 uint32_t imm32;
2469 uint32_t carry_out;
2470
2471 //EncodingSpecificOperations();
2472 switch (encoding)
2473 {
2474 case eEncodingT1:
2475 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2476 d = Bits32 (opcode, 2, 0);
2477 n = Bits32 (opcode, 5, 3);
2478 setflags = !InITBlock();
2479 imm32 = Bits32 (opcode, 8,6);
2480
2481 break;
2482
2483 case eEncodingT2:
2484 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2485 d = Bits32 (opcode, 10, 8);
2486 n = Bits32 (opcode, 10, 8);
2487 setflags = !InITBlock();
2488 imm32 = Bits32 (opcode, 7, 0);
2489
2490 break;
2491
2492 case eEncodingT3:
2493 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2494 // if Rn == '1101' then SEE ADD (SP plus immediate);
2495 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
2496 d = Bits32 (opcode, 11, 8);
2497 n = Bits32 (opcode, 19, 16);
2498 setflags = BitIsSet (opcode, 20);
2499 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2500
2501 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2502 if (BadReg (d) || (n == 15))
2503 return false;
2504
2505 break;
2506
2507 case eEncodingT4:
2508 {
2509 // if Rn == '1111' then SEE ADR;
2510 // if Rn == '1101' then SEE ADD (SP plus immediate);
2511 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2512 d = Bits32 (opcode, 11, 8);
2513 n = Bits32 (opcode, 19, 16);
2514 setflags = false;
2515 uint32_t i = Bit32 (opcode, 26);
2516 uint32_t imm3 = Bits32 (opcode, 14, 12);
2517 uint32_t imm8 = Bits32 (opcode, 7, 0);
2518 imm32 = (i << 11) | (imm3 << 8) | imm8;
2519
2520 // if BadReg(d) then UNPREDICTABLE;
2521 if (BadReg (d))
2522 return false;
2523
2524 break;
2525 }
2526 default:
2527 return false;
2528 }
2529
2530 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2531 if (!success)
2532 return false;
2533
2534 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2535 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2536
2537 RegisterInfo reg_n;
2538 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
2539
2540 EmulateInstruction::Context context;
2541 context.type = eContextArithmetic;
2542 context.SetRegisterPlusOffset (reg_n, imm32);
2543
2544 //R[d] = result;
2545 //if setflags then
2546 //APSR.N = result<31>;
2547 //APSR.Z = IsZeroBit(result);
2548 //APSR.C = carry;
2549 //APSR.V = overflow;
2550 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2551 return false;
2552
2553 }
2554 return true;
2555 }
2556
2557 // This instruction adds an immediate value to a register value, and writes the result to the destination
2558 // register. It can optionally update the condition flags based on the result.
2559 bool
EmulateADDImmARM(const uint32_t opcode,const ARMEncoding encoding)2560 EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
2561 {
2562 #if 0
2563 // ARM pseudo code...
2564 if ConditionPassed() then
2565 EncodingSpecificOperations();
2566 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2567 if d == 15 then
2568 ALUWritePC(result); // setflags is always FALSE here
2569 else
2570 R[d] = result;
2571 if setflags then
2572 APSR.N = result<31>;
2573 APSR.Z = IsZeroBit(result);
2574 APSR.C = carry;
2575 APSR.V = overflow;
2576 #endif
2577
2578 bool success = false;
2579
2580 if (ConditionPassed(opcode))
2581 {
2582 uint32_t Rd, Rn;
2583 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2584 bool setflags;
2585 switch (encoding)
2586 {
2587 case eEncodingA1:
2588 Rd = Bits32(opcode, 15, 12);
2589 Rn = Bits32(opcode, 19, 16);
2590 setflags = BitIsSet(opcode, 20);
2591 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2592 break;
2593 default:
2594 return false;
2595 }
2596
2597 // Read the first operand.
2598 uint32_t val1 = ReadCoreReg(Rn, &success);
2599 if (!success)
2600 return false;
2601
2602 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2603
2604 EmulateInstruction::Context context;
2605 context.type = eContextArithmetic;
2606 RegisterInfo dwarf_reg;
2607 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
2608 context.SetRegisterPlusOffset (dwarf_reg, imm32);
2609
2610 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2611 return false;
2612 }
2613 return true;
2614 }
2615
2616 // This instruction adds a register value and an optionally-shifted register value, and writes the result
2617 // to the destination register. It can optionally update the condition flags based on the result.
2618 bool
EmulateADDReg(const uint32_t opcode,const ARMEncoding encoding)2619 EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
2620 {
2621 #if 0
2622 // ARM pseudo code...
2623 if ConditionPassed() then
2624 EncodingSpecificOperations();
2625 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2626 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2627 if d == 15 then
2628 ALUWritePC(result); // setflags is always FALSE here
2629 else
2630 R[d] = result;
2631 if setflags then
2632 APSR.N = result<31>;
2633 APSR.Z = IsZeroBit(result);
2634 APSR.C = carry;
2635 APSR.V = overflow;
2636 #endif
2637
2638 bool success = false;
2639
2640 if (ConditionPassed(opcode))
2641 {
2642 uint32_t Rd, Rn, Rm;
2643 ARM_ShifterType shift_t;
2644 uint32_t shift_n; // the shift applied to the value read from Rm
2645 bool setflags;
2646 switch (encoding)
2647 {
2648 case eEncodingT1:
2649 Rd = Bits32(opcode, 2, 0);
2650 Rn = Bits32(opcode, 5, 3);
2651 Rm = Bits32(opcode, 8, 6);
2652 setflags = !InITBlock();
2653 shift_t = SRType_LSL;
2654 shift_n = 0;
2655 break;
2656 case eEncodingT2:
2657 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2658 Rm = Bits32(opcode, 6, 3);
2659 setflags = false;
2660 shift_t = SRType_LSL;
2661 shift_n = 0;
2662 if (Rn == 15 && Rm == 15)
2663 return false;
2664 if (Rd == 15 && InITBlock() && !LastInITBlock())
2665 return false;
2666 break;
2667 case eEncodingA1:
2668 Rd = Bits32(opcode, 15, 12);
2669 Rn = Bits32(opcode, 19, 16);
2670 Rm = Bits32(opcode, 3, 0);
2671 setflags = BitIsSet(opcode, 20);
2672 shift_n = DecodeImmShiftARM(opcode, shift_t);
2673 break;
2674 default:
2675 return false;
2676 }
2677
2678 // Read the first operand.
2679 uint32_t val1 = ReadCoreReg(Rn, &success);
2680 if (!success)
2681 return false;
2682
2683 // Read the second operand.
2684 uint32_t val2 = ReadCoreReg(Rm, &success);
2685 if (!success)
2686 return false;
2687
2688 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2689 if (!success)
2690 return false;
2691 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2692
2693 EmulateInstruction::Context context;
2694 context.type = eContextArithmetic;
2695 RegisterInfo op1_reg;
2696 RegisterInfo op2_reg;
2697 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2698 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
2699 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
2700
2701 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2702 return false;
2703 }
2704 return true;
2705 }
2706
2707 // Compare Negative (immediate) adds a register value and an immediate value.
2708 // It updates the condition flags based on the result, and discards the result.
2709 bool
EmulateCMNImm(const uint32_t opcode,const ARMEncoding encoding)2710 EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
2711 {
2712 #if 0
2713 // ARM pseudo code...
2714 if ConditionPassed() then
2715 EncodingSpecificOperations();
2716 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2717 APSR.N = result<31>;
2718 APSR.Z = IsZeroBit(result);
2719 APSR.C = carry;
2720 APSR.V = overflow;
2721 #endif
2722
2723 bool success = false;
2724
2725 uint32_t Rn; // the first operand
2726 uint32_t imm32; // the immediate value to be compared with
2727 switch (encoding) {
2728 case eEncodingT1:
2729 Rn = Bits32(opcode, 19, 16);
2730 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2731 if (Rn == 15)
2732 return false;
2733 break;
2734 case eEncodingA1:
2735 Rn = Bits32(opcode, 19, 16);
2736 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2737 break;
2738 default:
2739 return false;
2740 }
2741 // Read the register value from the operand register Rn.
2742 uint32_t reg_val = ReadCoreReg(Rn, &success);
2743 if (!success)
2744 return false;
2745
2746 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
2747
2748 EmulateInstruction::Context context;
2749 context.type = EmulateInstruction::eContextImmediate;
2750 context.SetNoArgs ();
2751 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2752 return false;
2753
2754 return true;
2755 }
2756
2757 // Compare Negative (register) adds a register value and an optionally-shifted register value.
2758 // It updates the condition flags based on the result, and discards the result.
2759 bool
EmulateCMNReg(const uint32_t opcode,const ARMEncoding encoding)2760 EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
2761 {
2762 #if 0
2763 // ARM pseudo code...
2764 if ConditionPassed() then
2765 EncodingSpecificOperations();
2766 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2767 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2768 APSR.N = result<31>;
2769 APSR.Z = IsZeroBit(result);
2770 APSR.C = carry;
2771 APSR.V = overflow;
2772 #endif
2773
2774 bool success = false;
2775
2776 uint32_t Rn; // the first operand
2777 uint32_t Rm; // the second operand
2778 ARM_ShifterType shift_t;
2779 uint32_t shift_n; // the shift applied to the value read from Rm
2780 switch (encoding) {
2781 case eEncodingT1:
2782 Rn = Bits32(opcode, 2, 0);
2783 Rm = Bits32(opcode, 5, 3);
2784 shift_t = SRType_LSL;
2785 shift_n = 0;
2786 break;
2787 case eEncodingT2:
2788 Rn = Bits32(opcode, 19, 16);
2789 Rm = Bits32(opcode, 3, 0);
2790 shift_n = DecodeImmShiftThumb(opcode, shift_t);
2791 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2792 if (Rn == 15 || BadReg(Rm))
2793 return false;
2794 break;
2795 case eEncodingA1:
2796 Rn = Bits32(opcode, 19, 16);
2797 Rm = Bits32(opcode, 3, 0);
2798 shift_n = DecodeImmShiftARM(opcode, shift_t);
2799 break;
2800 default:
2801 return false;
2802 }
2803 // Read the register value from register Rn.
2804 uint32_t val1 = ReadCoreReg(Rn, &success);
2805 if (!success)
2806 return false;
2807
2808 // Read the register value from register Rm.
2809 uint32_t val2 = ReadCoreReg(Rm, &success);
2810 if (!success)
2811 return false;
2812
2813 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2814 if (!success)
2815 return false;
2816 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
2817
2818 EmulateInstruction::Context context;
2819 context.type = EmulateInstruction::eContextImmediate;
2820 context.SetNoArgs();
2821 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2822 return false;
2823
2824 return true;
2825 }
2826
2827 // Compare (immediate) subtracts an immediate value from a register value.
2828 // It updates the condition flags based on the result, and discards the result.
2829 bool
EmulateCMPImm(const uint32_t opcode,const ARMEncoding encoding)2830 EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
2831 {
2832 #if 0
2833 // ARM pseudo code...
2834 if ConditionPassed() then
2835 EncodingSpecificOperations();
2836 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2837 APSR.N = result<31>;
2838 APSR.Z = IsZeroBit(result);
2839 APSR.C = carry;
2840 APSR.V = overflow;
2841 #endif
2842
2843 bool success = false;
2844
2845 uint32_t Rn; // the first operand
2846 uint32_t imm32; // the immediate value to be compared with
2847 switch (encoding) {
2848 case eEncodingT1:
2849 Rn = Bits32(opcode, 10, 8);
2850 imm32 = Bits32(opcode, 7, 0);
2851 break;
2852 case eEncodingT2:
2853 Rn = Bits32(opcode, 19, 16);
2854 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2855 if (Rn == 15)
2856 return false;
2857 break;
2858 case eEncodingA1:
2859 Rn = Bits32(opcode, 19, 16);
2860 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2861 break;
2862 default:
2863 return false;
2864 }
2865 // Read the register value from the operand register Rn.
2866 uint32_t reg_val = ReadCoreReg(Rn, &success);
2867 if (!success)
2868 return false;
2869
2870 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2871
2872 EmulateInstruction::Context context;
2873 context.type = EmulateInstruction::eContextImmediate;
2874 context.SetNoArgs ();
2875 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2876 return false;
2877
2878 return true;
2879 }
2880
2881 // Compare (register) subtracts an optionally-shifted register value from a register value.
2882 // It updates the condition flags based on the result, and discards the result.
2883 bool
EmulateCMPReg(const uint32_t opcode,const ARMEncoding encoding)2884 EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
2885 {
2886 #if 0
2887 // ARM pseudo code...
2888 if ConditionPassed() then
2889 EncodingSpecificOperations();
2890 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2891 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2892 APSR.N = result<31>;
2893 APSR.Z = IsZeroBit(result);
2894 APSR.C = carry;
2895 APSR.V = overflow;
2896 #endif
2897
2898 bool success = false;
2899
2900 uint32_t Rn; // the first operand
2901 uint32_t Rm; // the second operand
2902 ARM_ShifterType shift_t;
2903 uint32_t shift_n; // the shift applied to the value read from Rm
2904 switch (encoding) {
2905 case eEncodingT1:
2906 Rn = Bits32(opcode, 2, 0);
2907 Rm = Bits32(opcode, 5, 3);
2908 shift_t = SRType_LSL;
2909 shift_n = 0;
2910 break;
2911 case eEncodingT2:
2912 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2913 Rm = Bits32(opcode, 6, 3);
2914 shift_t = SRType_LSL;
2915 shift_n = 0;
2916 if (Rn < 8 && Rm < 8)
2917 return false;
2918 if (Rn == 15 || Rm == 15)
2919 return false;
2920 break;
2921 case eEncodingA1:
2922 Rn = Bits32(opcode, 19, 16);
2923 Rm = Bits32(opcode, 3, 0);
2924 shift_n = DecodeImmShiftARM(opcode, shift_t);
2925 break;
2926 default:
2927 return false;
2928 }
2929 // Read the register value from register Rn.
2930 uint32_t val1 = ReadCoreReg(Rn, &success);
2931 if (!success)
2932 return false;
2933
2934 // Read the register value from register Rm.
2935 uint32_t val2 = ReadCoreReg(Rm, &success);
2936 if (!success)
2937 return false;
2938
2939 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2940 if (!success)
2941 return false;
2942 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
2943
2944 EmulateInstruction::Context context;
2945 context.type = EmulateInstruction::eContextImmediate;
2946 context.SetNoArgs();
2947 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2948 return false;
2949
2950 return true;
2951 }
2952
2953 // Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2954 // shifting in copies of its sign bit, and writes the result to the destination register. It can
2955 // optionally update the condition flags based on the result.
2956 bool
EmulateASRImm(const uint32_t opcode,const ARMEncoding encoding)2957 EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
2958 {
2959 #if 0
2960 // ARM pseudo code...
2961 if ConditionPassed() then
2962 EncodingSpecificOperations();
2963 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2964 if d == 15 then // Can only occur for ARM encoding
2965 ALUWritePC(result); // setflags is always FALSE here
2966 else
2967 R[d] = result;
2968 if setflags then
2969 APSR.N = result<31>;
2970 APSR.Z = IsZeroBit(result);
2971 APSR.C = carry;
2972 // APSR.V unchanged
2973 #endif
2974
2975 return EmulateShiftImm (opcode, encoding, SRType_ASR);
2976 }
2977
2978 // Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2979 // shifting in copies of its sign bit, and writes the result to the destination register.
2980 // The variable number of bits is read from the bottom byte of a register. It can optionally update
2981 // the condition flags based on the result.
2982 bool
EmulateASRReg(const uint32_t opcode,const ARMEncoding encoding)2983 EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
2984 {
2985 #if 0
2986 // ARM pseudo code...
2987 if ConditionPassed() then
2988 EncodingSpecificOperations();
2989 shift_n = UInt(R[m]<7:0>);
2990 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2991 R[d] = result;
2992 if setflags then
2993 APSR.N = result<31>;
2994 APSR.Z = IsZeroBit(result);
2995 APSR.C = carry;
2996 // APSR.V unchanged
2997 #endif
2998
2999 return EmulateShiftReg (opcode, encoding, SRType_ASR);
3000 }
3001
3002 // Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
3003 // shifting in zeros, and writes the result to the destination register. It can optionally
3004 // update the condition flags based on the result.
3005 bool
EmulateLSLImm(const uint32_t opcode,const ARMEncoding encoding)3006 EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
3007 {
3008 #if 0
3009 // ARM pseudo code...
3010 if ConditionPassed() then
3011 EncodingSpecificOperations();
3012 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3013 if d == 15 then // Can only occur for ARM encoding
3014 ALUWritePC(result); // setflags is always FALSE here
3015 else
3016 R[d] = result;
3017 if setflags then
3018 APSR.N = result<31>;
3019 APSR.Z = IsZeroBit(result);
3020 APSR.C = carry;
3021 // APSR.V unchanged
3022 #endif
3023
3024 return EmulateShiftImm (opcode, encoding, SRType_LSL);
3025 }
3026
3027 // Logical Shift Left (register) shifts a register value left by a variable number of bits,
3028 // shifting in zeros, and writes the result to the destination register. The variable number
3029 // of bits is read from the bottom byte of a register. It can optionally update the condition
3030 // flags based on the result.
3031 bool
EmulateLSLReg(const uint32_t opcode,const ARMEncoding encoding)3032 EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
3033 {
3034 #if 0
3035 // ARM pseudo code...
3036 if ConditionPassed() then
3037 EncodingSpecificOperations();
3038 shift_n = UInt(R[m]<7:0>);
3039 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3040 R[d] = result;
3041 if setflags then
3042 APSR.N = result<31>;
3043 APSR.Z = IsZeroBit(result);
3044 APSR.C = carry;
3045 // APSR.V unchanged
3046 #endif
3047
3048 return EmulateShiftReg (opcode, encoding, SRType_LSL);
3049 }
3050
3051 // Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
3052 // shifting in zeros, and writes the result to the destination register. It can optionally
3053 // update the condition flags based on the result.
3054 bool
EmulateLSRImm(const uint32_t opcode,const ARMEncoding encoding)3055 EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
3056 {
3057 #if 0
3058 // ARM pseudo code...
3059 if ConditionPassed() then
3060 EncodingSpecificOperations();
3061 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3062 if d == 15 then // Can only occur for ARM encoding
3063 ALUWritePC(result); // setflags is always FALSE here
3064 else
3065 R[d] = result;
3066 if setflags then
3067 APSR.N = result<31>;
3068 APSR.Z = IsZeroBit(result);
3069 APSR.C = carry;
3070 // APSR.V unchanged
3071 #endif
3072
3073 return EmulateShiftImm (opcode, encoding, SRType_LSR);
3074 }
3075
3076 // Logical Shift Right (register) shifts a register value right by a variable number of bits,
3077 // shifting in zeros, and writes the result to the destination register. The variable number
3078 // of bits is read from the bottom byte of a register. It can optionally update the condition
3079 // flags based on the result.
3080 bool
EmulateLSRReg(const uint32_t opcode,const ARMEncoding encoding)3081 EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
3082 {
3083 #if 0
3084 // ARM pseudo code...
3085 if ConditionPassed() then
3086 EncodingSpecificOperations();
3087 shift_n = UInt(R[m]<7:0>);
3088 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3089 R[d] = result;
3090 if setflags then
3091 APSR.N = result<31>;
3092 APSR.Z = IsZeroBit(result);
3093 APSR.C = carry;
3094 // APSR.V unchanged
3095 #endif
3096
3097 return EmulateShiftReg (opcode, encoding, SRType_LSR);
3098 }
3099
3100 // Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3101 // The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3102 // It can optionally update the condition flags based on the result.
3103 bool
EmulateRORImm(const uint32_t opcode,const ARMEncoding encoding)3104 EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
3105 {
3106 #if 0
3107 // ARM pseudo code...
3108 if ConditionPassed() then
3109 EncodingSpecificOperations();
3110 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3111 if d == 15 then // Can only occur for ARM encoding
3112 ALUWritePC(result); // setflags is always FALSE here
3113 else
3114 R[d] = result;
3115 if setflags then
3116 APSR.N = result<31>;
3117 APSR.Z = IsZeroBit(result);
3118 APSR.C = carry;
3119 // APSR.V unchanged
3120 #endif
3121
3122 return EmulateShiftImm (opcode, encoding, SRType_ROR);
3123 }
3124
3125 // Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3126 // The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3127 // The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3128 // flags based on the result.
3129 bool
EmulateRORReg(const uint32_t opcode,const ARMEncoding encoding)3130 EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
3131 {
3132 #if 0
3133 // ARM pseudo code...
3134 if ConditionPassed() then
3135 EncodingSpecificOperations();
3136 shift_n = UInt(R[m]<7:0>);
3137 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3138 R[d] = result;
3139 if setflags then
3140 APSR.N = result<31>;
3141 APSR.Z = IsZeroBit(result);
3142 APSR.C = carry;
3143 // APSR.V unchanged
3144 #endif
3145
3146 return EmulateShiftReg (opcode, encoding, SRType_ROR);
3147 }
3148
3149 // Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3150 // with the carry flag shifted into bit [31].
3151 //
3152 // RRX can optionally update the condition flags based on the result.
3153 // In that case, bit [0] is shifted into the carry flag.
3154 bool
EmulateRRX(const uint32_t opcode,const ARMEncoding encoding)3155 EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
3156 {
3157 #if 0
3158 // ARM pseudo code...
3159 if ConditionPassed() then
3160 EncodingSpecificOperations();
3161 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3162 if d == 15 then // Can only occur for ARM encoding
3163 ALUWritePC(result); // setflags is always FALSE here
3164 else
3165 R[d] = result;
3166 if setflags then
3167 APSR.N = result<31>;
3168 APSR.Z = IsZeroBit(result);
3169 APSR.C = carry;
3170 // APSR.V unchanged
3171 #endif
3172
3173 return EmulateShiftImm (opcode, encoding, SRType_RRX);
3174 }
3175
3176 bool
EmulateShiftImm(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3177 EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
3178 {
3179 // assert(shift_type == SRType_ASR
3180 // || shift_type == SRType_LSL
3181 // || shift_type == SRType_LSR
3182 // || shift_type == SRType_ROR
3183 // || shift_type == SRType_RRX);
3184
3185 bool success = false;
3186
3187 if (ConditionPassed(opcode))
3188 {
3189 uint32_t Rd; // the destination register
3190 uint32_t Rm; // the first operand register
3191 uint32_t imm5; // encoding for the shift amount
3192 uint32_t carry; // the carry bit after the shift operation
3193 bool setflags;
3194
3195 // Special case handling!
3196 // A8.6.139 ROR (immediate) -- Encoding T1
3197 ARMEncoding use_encoding = encoding;
3198 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
3199 {
3200 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3201 // have the same decoding of bit fields as the other Thumb2 shift operations.
3202 use_encoding = eEncodingT2;
3203 }
3204
3205 switch (use_encoding) {
3206 case eEncodingT1:
3207 // Due to the above special case handling!
3208 if (shift_type == SRType_ROR)
3209 return false;
3210
3211 Rd = Bits32(opcode, 2, 0);
3212 Rm = Bits32(opcode, 5, 3);
3213 setflags = !InITBlock();
3214 imm5 = Bits32(opcode, 10, 6);
3215 break;
3216 case eEncodingT2:
3217 // A8.6.141 RRX
3218 // There's no imm form of RRX instructions.
3219 if (shift_type == SRType_RRX)
3220 return false;
3221
3222 Rd = Bits32(opcode, 11, 8);
3223 Rm = Bits32(opcode, 3, 0);
3224 setflags = BitIsSet(opcode, 20);
3225 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3226 if (BadReg(Rd) || BadReg(Rm))
3227 return false;
3228 break;
3229 case eEncodingA1:
3230 Rd = Bits32(opcode, 15, 12);
3231 Rm = Bits32(opcode, 3, 0);
3232 setflags = BitIsSet(opcode, 20);
3233 imm5 = Bits32(opcode, 11, 7);
3234 break;
3235 default:
3236 return false;
3237 }
3238
3239 // A8.6.139 ROR (immediate)
3240 if (shift_type == SRType_ROR && imm5 == 0)
3241 shift_type = SRType_RRX;
3242
3243 // Get the first operand.
3244 uint32_t value = ReadCoreReg (Rm, &success);
3245 if (!success)
3246 return false;
3247
3248 // Decode the shift amount if not RRX.
3249 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3250
3251 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3252 if (!success)
3253 return false;
3254
3255 // The context specifies that an immediate is to be moved into Rd.
3256 EmulateInstruction::Context context;
3257 context.type = EmulateInstruction::eContextImmediate;
3258 context.SetNoArgs ();
3259
3260 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3261 return false;
3262 }
3263 return true;
3264 }
3265
3266 bool
EmulateShiftReg(const uint32_t opcode,const ARMEncoding encoding,ARM_ShifterType shift_type)3267 EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
3268 {
3269 // assert(shift_type == SRType_ASR
3270 // || shift_type == SRType_LSL
3271 // || shift_type == SRType_LSR
3272 // || shift_type == SRType_ROR);
3273
3274 bool success = false;
3275
3276 if (ConditionPassed(opcode))
3277 {
3278 uint32_t Rd; // the destination register
3279 uint32_t Rn; // the first operand register
3280 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3281 uint32_t carry; // the carry bit after the shift operation
3282 bool setflags;
3283 switch (encoding) {
3284 case eEncodingT1:
3285 Rd = Bits32(opcode, 2, 0);
3286 Rn = Rd;
3287 Rm = Bits32(opcode, 5, 3);
3288 setflags = !InITBlock();
3289 break;
3290 case eEncodingT2:
3291 Rd = Bits32(opcode, 11, 8);
3292 Rn = Bits32(opcode, 19, 16);
3293 Rm = Bits32(opcode, 3, 0);
3294 setflags = BitIsSet(opcode, 20);
3295 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3296 return false;
3297 break;
3298 case eEncodingA1:
3299 Rd = Bits32(opcode, 15, 12);
3300 Rn = Bits32(opcode, 3, 0);
3301 Rm = Bits32(opcode, 11, 8);
3302 setflags = BitIsSet(opcode, 20);
3303 if (Rd == 15 || Rn == 15 || Rm == 15)
3304 return false;
3305 break;
3306 default:
3307 return false;
3308 }
3309
3310 // Get the first operand.
3311 uint32_t value = ReadCoreReg (Rn, &success);
3312 if (!success)
3313 return false;
3314 // Get the Rm register content.
3315 uint32_t val = ReadCoreReg (Rm, &success);
3316 if (!success)
3317 return false;
3318
3319 // Get the shift amount.
3320 uint32_t amt = Bits32(val, 7, 0);
3321
3322 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3323 if (!success)
3324 return false;
3325
3326 // The context specifies that an immediate is to be moved into Rd.
3327 EmulateInstruction::Context context;
3328 context.type = EmulateInstruction::eContextImmediate;
3329 context.SetNoArgs ();
3330
3331 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3332 return false;
3333 }
3334 return true;
3335 }
3336
3337 // LDM loads multiple registers from consecutive memory locations, using an
3338 // address from a base register. Optionally the address just above the highest of those locations
3339 // can be written back to the base register.
3340 bool
EmulateLDM(const uint32_t opcode,const ARMEncoding encoding)3341 EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
3342 {
3343 #if 0
3344 // ARM pseudo code...
3345 if ConditionPassed()
3346 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3347 address = R[n];
3348
3349 for i = 0 to 14
3350 if registers<i> == '1' then
3351 R[i] = MemA[address, 4]; address = address + 4;
3352 if registers<15> == '1' then
3353 LoadWritePC (MemA[address, 4]);
3354
3355 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3356 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3357
3358 #endif
3359
3360 bool success = false;
3361 bool conditional = false;
3362 if (ConditionPassed(opcode, &conditional))
3363 {
3364 uint32_t n;
3365 uint32_t registers = 0;
3366 bool wback;
3367 const uint32_t addr_byte_size = GetAddressByteSize();
3368 switch (encoding)
3369 {
3370 case eEncodingT1:
3371 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
3372 n = Bits32 (opcode, 10, 8);
3373 registers = Bits32 (opcode, 7, 0);
3374 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3375 wback = BitIsClear (registers, n);
3376 // if BitCount(registers) < 1 then UNPREDICTABLE;
3377 if (BitCount(registers) < 1)
3378 return false;
3379 break;
3380 case eEncodingT2:
3381 // if W == '1' && Rn == '1101' then SEE POP;
3382 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3383 n = Bits32 (opcode, 19, 16);
3384 registers = Bits32 (opcode, 15, 0);
3385 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3386 wback = BitIsSet (opcode, 21);
3387
3388 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
3389 if ((n == 15)
3390 || (BitCount (registers) < 2)
3391 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3392 return false;
3393
3394 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3395 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
3396 return false;
3397
3398 // if wback && registers<n> == '1' then UNPREDICTABLE;
3399 if (wback
3400 && BitIsSet (registers, n))
3401 return false;
3402 break;
3403
3404 case eEncodingA1:
3405 n = Bits32 (opcode, 19, 16);
3406 registers = Bits32 (opcode, 15, 0);
3407 wback = BitIsSet (opcode, 21);
3408 if ((n == 15)
3409 || (BitCount (registers) < 1))
3410 return false;
3411 break;
3412 default:
3413 return false;
3414 }
3415
3416 int32_t offset = 0;
3417 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3418 if (!success)
3419 return false;
3420
3421 EmulateInstruction::Context context;
3422 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3423 RegisterInfo dwarf_reg;
3424 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3425 context.SetRegisterPlusOffset (dwarf_reg, offset);
3426
3427 for (int i = 0; i < 14; ++i)
3428 {
3429 if (BitIsSet (registers, i))
3430 {
3431 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3432 context.SetRegisterPlusOffset (dwarf_reg, offset);
3433 if (wback && (n == 13)) // Pop Instruction
3434 {
3435 if (conditional)
3436 context.type = EmulateInstruction::eContextRegisterLoad;
3437 else
3438 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3439 }
3440
3441 // R[i] = MemA [address, 4]; address = address + 4;
3442 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3443 if (!success)
3444 return false;
3445
3446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3447 return false;
3448
3449 offset += addr_byte_size;
3450 }
3451 }
3452
3453 if (BitIsSet (registers, 15))
3454 {
3455 //LoadWritePC (MemA [address, 4]);
3456 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3457 context.SetRegisterPlusOffset (dwarf_reg, offset);
3458 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3459 if (!success)
3460 return false;
3461 // In ARMv5T and above, this is an interworking branch.
3462 if (!LoadWritePC(context, data))
3463 return false;
3464 }
3465
3466 if (wback && BitIsClear (registers, n))
3467 {
3468 // R[n] = R[n] + 4 * BitCount (registers)
3469 int32_t offset = addr_byte_size * BitCount (registers);
3470 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3471 context.SetRegisterPlusOffset (dwarf_reg, offset);
3472
3473 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3474 return false;
3475 }
3476 if (wback && BitIsSet (registers, n))
3477 // R[n] bits(32) UNKNOWN;
3478 return WriteBits32Unknown (n);
3479 }
3480 return true;
3481 }
3482
3483 // LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3484 // The consecutive memory locations end at this address and the address just below the lowest of those locations
3485 // can optionally be written back to the base register.
3486 bool
EmulateLDMDA(const uint32_t opcode,const ARMEncoding encoding)3487 EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
3488 {
3489 #if 0
3490 // ARM pseudo code...
3491 if ConditionPassed() then
3492 EncodingSpecificOperations();
3493 address = R[n] - 4*BitCount(registers) + 4;
3494
3495 for i = 0 to 14
3496 if registers<i> == '1' then
3497 R[i] = MemA[address,4]; address = address + 4;
3498
3499 if registers<15> == '1' then
3500 LoadWritePC(MemA[address,4]);
3501
3502 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3503 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3504 #endif
3505
3506 bool success = false;
3507
3508 if (ConditionPassed(opcode))
3509 {
3510 uint32_t n;
3511 uint32_t registers = 0;
3512 bool wback;
3513 const uint32_t addr_byte_size = GetAddressByteSize();
3514
3515 // EncodingSpecificOperations();
3516 switch (encoding)
3517 {
3518 case eEncodingA1:
3519 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3520 n = Bits32 (opcode, 19, 16);
3521 registers = Bits32 (opcode, 15, 0);
3522 wback = BitIsSet (opcode, 21);
3523
3524 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3525 if ((n == 15) || (BitCount (registers) < 1))
3526 return false;
3527
3528 break;
3529
3530 default:
3531 return false;
3532 }
3533 // address = R[n] - 4*BitCount(registers) + 4;
3534
3535 int32_t offset = 0;
3536 addr_t Rn = ReadCoreReg (n, &success);
3537
3538 if (!success)
3539 return false;
3540
3541 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3542
3543 EmulateInstruction::Context context;
3544 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3545 RegisterInfo dwarf_reg;
3546 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3547 context.SetRegisterPlusOffset (dwarf_reg, offset);
3548
3549 // for i = 0 to 14
3550 for (int i = 0; i < 14; ++i)
3551 {
3552 // if registers<i> == '1' then
3553 if (BitIsSet (registers, i))
3554 {
3555 // R[i] = MemA[address,4]; address = address + 4;
3556 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3557 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3558 if (!success)
3559 return false;
3560 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3561 return false;
3562 offset += addr_byte_size;
3563 }
3564 }
3565
3566 // if registers<15> == '1' then
3567 // LoadWritePC(MemA[address,4]);
3568 if (BitIsSet (registers, 15))
3569 {
3570 context.SetRegisterPlusOffset (dwarf_reg, offset);
3571 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3572 if (!success)
3573 return false;
3574 // In ARMv5T and above, this is an interworking branch.
3575 if (!LoadWritePC(context, data))
3576 return false;
3577 }
3578
3579 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3580 if (wback && BitIsClear (registers, n))
3581 {
3582 if (!success)
3583 return false;
3584
3585 offset = (addr_byte_size * BitCount (registers)) * -1;
3586 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3587 context.SetImmediateSigned (offset);
3588 addr_t addr = Rn + offset;
3589 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3590 return false;
3591 }
3592
3593 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3594 if (wback && BitIsSet (registers, n))
3595 return WriteBits32Unknown (n);
3596 }
3597 return true;
3598 }
3599
3600 // LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3601 // consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3602 // be optionally written back to the base register.
3603 bool
EmulateLDMDB(const uint32_t opcode,const ARMEncoding encoding)3604 EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
3605 {
3606 #if 0
3607 // ARM pseudo code...
3608 if ConditionPassed() then
3609 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3610 address = R[n] - 4*BitCount(registers);
3611
3612 for i = 0 to 14
3613 if registers<i> == '1' then
3614 R[i] = MemA[address,4]; address = address + 4;
3615 if registers<15> == '1' then
3616 LoadWritePC(MemA[address,4]);
3617
3618 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3619 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3620 #endif
3621
3622 bool success = false;
3623
3624 if (ConditionPassed(opcode))
3625 {
3626 uint32_t n;
3627 uint32_t registers = 0;
3628 bool wback;
3629 const uint32_t addr_byte_size = GetAddressByteSize();
3630 switch (encoding)
3631 {
3632 case eEncodingT1:
3633 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3634 n = Bits32 (opcode, 19, 16);
3635 registers = Bits32 (opcode, 15, 0);
3636 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
3637 wback = BitIsSet (opcode, 21);
3638
3639 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
3640 if ((n == 15)
3641 || (BitCount (registers) < 2)
3642 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3643 return false;
3644
3645 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3646 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
3647 return false;
3648
3649 // if wback && registers<n> == '1' then UNPREDICTABLE;
3650 if (wback && BitIsSet (registers, n))
3651 return false;
3652
3653 break;
3654
3655 case eEncodingA1:
3656 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3657 n = Bits32 (opcode, 19, 16);
3658 registers = Bits32 (opcode, 15, 0);
3659 wback = BitIsSet (opcode, 21);
3660
3661 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3662 if ((n == 15) || (BitCount (registers) < 1))
3663 return false;
3664
3665 break;
3666
3667 default:
3668 return false;
3669 }
3670
3671 // address = R[n] - 4*BitCount(registers);
3672
3673 int32_t offset = 0;
3674 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3675
3676 if (!success)
3677 return false;
3678
3679 addr_t address = Rn - (addr_byte_size * BitCount (registers));
3680 EmulateInstruction::Context context;
3681 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3682 RegisterInfo dwarf_reg;
3683 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3684 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
3685
3686 for (int i = 0; i < 14; ++i)
3687 {
3688 if (BitIsSet (registers, i))
3689 {
3690 // R[i] = MemA[address,4]; address = address + 4;
3691 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3692 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3693 if (!success)
3694 return false;
3695
3696 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3697 return false;
3698
3699 offset += addr_byte_size;
3700 }
3701 }
3702
3703 // if registers<15> == '1' then
3704 // LoadWritePC(MemA[address,4]);
3705 if (BitIsSet (registers, 15))
3706 {
3707 context.SetRegisterPlusOffset (dwarf_reg, offset);
3708 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3709 if (!success)
3710 return false;
3711 // In ARMv5T and above, this is an interworking branch.
3712 if (!LoadWritePC(context, data))
3713 return false;
3714 }
3715
3716 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3717 if (wback && BitIsClear (registers, n))
3718 {
3719 if (!success)
3720 return false;
3721
3722 offset = (addr_byte_size * BitCount (registers)) * -1;
3723 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3724 context.SetImmediateSigned (offset);
3725 addr_t addr = Rn + offset;
3726 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3727 return false;
3728 }
3729
3730 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3731 if (wback && BitIsSet (registers, n))
3732 return WriteBits32Unknown (n);
3733 }
3734 return true;
3735 }
3736
3737 // LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3738 // consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3739 // optinoally be written back to the base register.
3740 bool
EmulateLDMIB(const uint32_t opcode,const ARMEncoding encoding)3741 EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
3742 {
3743 #if 0
3744 if ConditionPassed() then
3745 EncodingSpecificOperations();
3746 address = R[n] + 4;
3747
3748 for i = 0 to 14
3749 if registers<i> == '1' then
3750 R[i] = MemA[address,4]; address = address + 4;
3751 if registers<15> == '1' then
3752 LoadWritePC(MemA[address,4]);
3753
3754 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3755 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3756 #endif
3757
3758 bool success = false;
3759
3760 if (ConditionPassed(opcode))
3761 {
3762 uint32_t n;
3763 uint32_t registers = 0;
3764 bool wback;
3765 const uint32_t addr_byte_size = GetAddressByteSize();
3766 switch (encoding)
3767 {
3768 case eEncodingA1:
3769 // n = UInt(Rn); registers = register_list; wback = (W == '1');
3770 n = Bits32 (opcode, 19, 16);
3771 registers = Bits32 (opcode, 15, 0);
3772 wback = BitIsSet (opcode, 21);
3773
3774 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3775 if ((n == 15) || (BitCount (registers) < 1))
3776 return false;
3777
3778 break;
3779 default:
3780 return false;
3781 }
3782 // address = R[n] + 4;
3783
3784 int32_t offset = 0;
3785 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3786
3787 if (!success)
3788 return false;
3789
3790 addr_t address = Rn + addr_byte_size;
3791
3792 EmulateInstruction::Context context;
3793 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3794 RegisterInfo dwarf_reg;
3795 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
3796 context.SetRegisterPlusOffset (dwarf_reg, offset);
3797
3798 for (int i = 0; i < 14; ++i)
3799 {
3800 if (BitIsSet (registers, i))
3801 {
3802 // R[i] = MemA[address,4]; address = address + 4;
3803
3804 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
3805 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3806 if (!success)
3807 return false;
3808
3809 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3810 return false;
3811
3812 offset += addr_byte_size;
3813 }
3814 }
3815
3816 // if registers<15> == '1' then
3817 // LoadWritePC(MemA[address,4]);
3818 if (BitIsSet (registers, 15))
3819 {
3820 context.SetRegisterPlusOffset (dwarf_reg, offset);
3821 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3822 if (!success)
3823 return false;
3824 // In ARMv5T and above, this is an interworking branch.
3825 if (!LoadWritePC(context, data))
3826 return false;
3827 }
3828
3829 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3830 if (wback && BitIsClear (registers, n))
3831 {
3832 if (!success)
3833 return false;
3834
3835 offset = addr_byte_size * BitCount (registers);
3836 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3837 context.SetImmediateSigned (offset);
3838 addr_t addr = Rn + offset;
3839 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3840 return false;
3841 }
3842
3843 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3844 if (wback && BitIsSet (registers, n))
3845 return WriteBits32Unknown (n);
3846 }
3847 return true;
3848 }
3849
3850 // Load Register (immediate) calculates an address from a base register value and
3851 // an immediate offset, loads a word from memory, and writes to a register.
3852 // LDR (immediate, Thumb)
3853 bool
EmulateLDRRtRnImm(const uint32_t opcode,const ARMEncoding encoding)3854 EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
3855 {
3856 #if 0
3857 // ARM pseudo code...
3858 if (ConditionPassed())
3859 {
3860 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3861 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3862 address = if index then offset_addr else R[n];
3863 data = MemU[address,4];
3864 if wback then R[n] = offset_addr;
3865 if t == 15 then
3866 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3867 elsif UnalignedSupport() || address<1:0> = '00' then
3868 R[t] = data;
3869 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3870 }
3871 #endif
3872
3873 bool success = false;
3874
3875 if (ConditionPassed(opcode))
3876 {
3877 uint32_t Rt; // the destination register
3878 uint32_t Rn; // the base register
3879 uint32_t imm32; // the immediate offset used to form the address
3880 addr_t offset_addr; // the offset address
3881 addr_t address; // the calculated address
3882 uint32_t data; // the literal data value from memory load
3883 bool add, index, wback;
3884 switch (encoding) {
3885 case eEncodingT1:
3886 Rt = Bits32(opcode, 2, 0);
3887 Rn = Bits32(opcode, 5, 3);
3888 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3889 // index = TRUE; add = TRUE; wback = FALSE
3890 add = true;
3891 index = true;
3892 wback = false;
3893
3894 break;
3895
3896 case eEncodingT2:
3897 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
3898 Rt = Bits32 (opcode, 10, 8);
3899 Rn = 13;
3900 imm32 = Bits32 (opcode, 7, 0) << 2;
3901
3902 // index = TRUE; add = TRUE; wback = FALSE;
3903 index = true;
3904 add = true;
3905 wback = false;
3906
3907 break;
3908
3909 case eEncodingT3:
3910 // if Rn == '1111' then SEE LDR (literal);
3911 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3912 Rt = Bits32 (opcode, 15, 12);
3913 Rn = Bits32 (opcode, 19, 16);
3914 imm32 = Bits32 (opcode, 11, 0);
3915
3916 // index = TRUE; add = TRUE; wback = FALSE;
3917 index = true;
3918 add = true;
3919 wback = false;
3920
3921 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3922 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3923 return false;
3924
3925 break;
3926
3927 case eEncodingT4:
3928 // if Rn == '1111' then SEE LDR (literal);
3929 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3930 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3931 // if P == '0' && W == '0' then UNDEFINED;
3932 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3933 return false;
3934
3935 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3936 Rt = Bits32 (opcode, 15, 12);
3937 Rn = Bits32 (opcode, 19, 16);
3938 imm32 = Bits32 (opcode, 7, 0);
3939
3940 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
3941 index = BitIsSet (opcode, 10);
3942 add = BitIsSet (opcode, 9);
3943 wback = BitIsSet (opcode, 8);
3944
3945 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3946 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3947 return false;
3948
3949 break;
3950
3951 default:
3952 return false;
3953 }
3954 uint32_t base = ReadCoreReg (Rn, &success);
3955 if (!success)
3956 return false;
3957 if (add)
3958 offset_addr = base + imm32;
3959 else
3960 offset_addr = base - imm32;
3961
3962 address = (index ? offset_addr : base);
3963
3964 RegisterInfo base_reg;
3965 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
3966 if (wback)
3967 {
3968 EmulateInstruction::Context ctx;
3969 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3970 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
3971
3972 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3973 return false;
3974 }
3975
3976 // Prepare to write to the Rt register.
3977 EmulateInstruction::Context context;
3978 context.type = EmulateInstruction::eContextRegisterLoad;
3979 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
3980
3981 // Read memory from the address.
3982 data = MemURead(context, address, 4, 0, &success);
3983 if (!success)
3984 return false;
3985
3986 if (Rt == 15)
3987 {
3988 if (Bits32(address, 1, 0) == 0)
3989 {
3990 if (!LoadWritePC(context, data))
3991 return false;
3992 }
3993 else
3994 return false;
3995 }
3996 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3997 {
3998 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3999 return false;
4000 }
4001 else
4002 WriteBits32Unknown (Rt);
4003 }
4004 return true;
4005 }
4006
4007 // STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
4008 // from a base register. The consecutive memory locations start at this address, and teh address just above the last
4009 // of those locations can optionally be written back to the base register.
4010 bool
EmulateSTM(const uint32_t opcode,const ARMEncoding encoding)4011 EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
4012 {
4013 #if 0
4014 if ConditionPassed() then
4015 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4016 address = R[n];
4017
4018 for i = 0 to 14
4019 if registers<i> == '1' then
4020 if i == n && wback && i != LowestSetBit(registers) then
4021 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4022 else
4023 MemA[address,4] = R[i];
4024 address = address + 4;
4025
4026 if registers<15> == '1' then // Only possible for encoding A1
4027 MemA[address,4] = PCStoreValue();
4028 if wback then R[n] = R[n] + 4*BitCount(registers);
4029 #endif
4030
4031 bool success = false;
4032
4033 if (ConditionPassed(opcode))
4034 {
4035 uint32_t n;
4036 uint32_t registers = 0;
4037 bool wback;
4038 const uint32_t addr_byte_size = GetAddressByteSize();
4039
4040 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4041 switch (encoding)
4042 {
4043 case eEncodingT1:
4044 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4045 n = Bits32 (opcode, 10, 8);
4046 registers = Bits32 (opcode, 7, 0);
4047 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4048 wback = true;
4049
4050 // if BitCount(registers) < 1 then UNPREDICTABLE;
4051 if (BitCount (registers) < 1)
4052 return false;
4053
4054 break;
4055
4056 case eEncodingT2:
4057 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4058 n = Bits32 (opcode, 19, 16);
4059 registers = Bits32 (opcode, 15, 0);
4060 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4061 wback = BitIsSet (opcode, 21);
4062
4063 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4064 if ((n == 15) || (BitCount (registers) < 2))
4065 return false;
4066
4067 // if wback && registers<n> == '1' then UNPREDICTABLE;
4068 if (wback && BitIsSet (registers, n))
4069 return false;
4070
4071 break;
4072
4073 case eEncodingA1:
4074 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4075 n = Bits32 (opcode, 19, 16);
4076 registers = Bits32 (opcode, 15, 0);
4077 wback = BitIsSet (opcode, 21);
4078
4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080 if ((n == 15) || (BitCount (registers) < 1))
4081 return false;
4082
4083 break;
4084
4085 default:
4086 return false;
4087 }
4088
4089 // address = R[n];
4090 int32_t offset = 0;
4091 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4092 if (!success)
4093 return false;
4094
4095 EmulateInstruction::Context context;
4096 context.type = EmulateInstruction::eContextRegisterStore;
4097 RegisterInfo base_reg;
4098 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4099
4100 // for i = 0 to 14
4101 uint32_t lowest_set_bit = 14;
4102 for (uint32_t i = 0; i < 14; ++i)
4103 {
4104 // if registers<i> == '1' then
4105 if (BitIsSet (registers, i))
4106 {
4107 if (i < lowest_set_bit)
4108 lowest_set_bit = i;
4109 // if i == n && wback && i != LowestSetBit(registers) then
4110 if ((i == n) && wback && (i != lowest_set_bit))
4111 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4112 WriteBits32UnknownToMemory (address + offset);
4113 else
4114 {
4115 // MemA[address,4] = R[i];
4116 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4117 if (!success)
4118 return false;
4119
4120 RegisterInfo data_reg;
4121 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4122 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
4123 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4124 return false;
4125 }
4126
4127 // address = address + 4;
4128 offset += addr_byte_size;
4129 }
4130 }
4131
4132 // if registers<15> == '1' then // Only possible for encoding A1
4133 // MemA[address,4] = PCStoreValue();
4134 if (BitIsSet (registers, 15))
4135 {
4136 RegisterInfo pc_reg;
4137 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4138 context.SetRegisterPlusOffset (pc_reg, 8);
4139 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4140 if (!success)
4141 return false;
4142
4143 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4144 return false;
4145 }
4146
4147 // if wback then R[n] = R[n] + 4*BitCount(registers);
4148 if (wback)
4149 {
4150 offset = addr_byte_size * BitCount (registers);
4151 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4152 context.SetImmediateSigned (offset);
4153 addr_t data = address + offset;
4154 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4155 return false;
4156 }
4157 }
4158 return true;
4159 }
4160
4161 // STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4162 // from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4163 // of those locations can optionally be written back to the base register.
4164 bool
EmulateSTMDA(const uint32_t opcode,const ARMEncoding encoding)4165 EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
4166 {
4167 #if 0
4168 if ConditionPassed() then
4169 EncodingSpecificOperations();
4170 address = R[n] - 4*BitCount(registers) + 4;
4171
4172 for i = 0 to 14
4173 if registers<i> == '1' then
4174 if i == n && wback && i != LowestSetBit(registers) then
4175 MemA[address,4] = bits(32) UNKNOWN;
4176 else
4177 MemA[address,4] = R[i];
4178 address = address + 4;
4179
4180 if registers<15> == '1' then
4181 MemA[address,4] = PCStoreValue();
4182
4183 if wback then R[n] = R[n] - 4*BitCount(registers);
4184 #endif
4185
4186 bool success = false;
4187
4188 if (ConditionPassed(opcode))
4189 {
4190 uint32_t n;
4191 uint32_t registers = 0;
4192 bool wback;
4193 const uint32_t addr_byte_size = GetAddressByteSize();
4194
4195 // EncodingSpecificOperations();
4196 switch (encoding)
4197 {
4198 case eEncodingA1:
4199 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4200 n = Bits32 (opcode, 19, 16);
4201 registers = Bits32 (opcode, 15, 0);
4202 wback = BitIsSet (opcode, 21);
4203
4204 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4205 if ((n == 15) || (BitCount (registers) < 1))
4206 return false;
4207 break;
4208 default:
4209 return false;
4210 }
4211
4212 // address = R[n] - 4*BitCount(registers) + 4;
4213 int32_t offset = 0;
4214 addr_t Rn = ReadCoreReg (n, &success);
4215 if (!success)
4216 return false;
4217
4218 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
4219
4220 EmulateInstruction::Context context;
4221 context.type = EmulateInstruction::eContextRegisterStore;
4222 RegisterInfo base_reg;
4223 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4224
4225 // for i = 0 to 14
4226 uint32_t lowest_bit_set = 14;
4227 for (uint32_t i = 0; i < 14; ++i)
4228 {
4229 // if registers<i> == '1' then
4230 if (BitIsSet (registers, i))
4231 {
4232 if (i < lowest_bit_set)
4233 lowest_bit_set = i;
4234 //if i == n && wback && i != LowestSetBit(registers) then
4235 if ((i == n) && wback && (i != lowest_bit_set))
4236 // MemA[address,4] = bits(32) UNKNOWN;
4237 WriteBits32UnknownToMemory (address + offset);
4238 else
4239 {
4240 // MemA[address,4] = R[i];
4241 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4242 if (!success)
4243 return false;
4244
4245 RegisterInfo data_reg;
4246 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4247 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4248 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4249 return false;
4250 }
4251
4252 // address = address + 4;
4253 offset += addr_byte_size;
4254 }
4255 }
4256
4257 // if registers<15> == '1' then
4258 // MemA[address,4] = PCStoreValue();
4259 if (BitIsSet (registers, 15))
4260 {
4261 RegisterInfo pc_reg;
4262 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4263 context.SetRegisterPlusOffset (pc_reg, 8);
4264 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4265 if (!success)
4266 return false;
4267
4268 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4269 return false;
4270 }
4271
4272 // if wback then R[n] = R[n] - 4*BitCount(registers);
4273 if (wback)
4274 {
4275 offset = (addr_byte_size * BitCount (registers)) * -1;
4276 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4277 context.SetImmediateSigned (offset);
4278 addr_t data = Rn + offset;
4279 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4280 return false;
4281 }
4282 }
4283 return true;
4284 }
4285
4286 // STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4287 // from a base register. The consecutive memory locations end just below this address, and the address of the first of
4288 // those locations can optionally be written back to the base register.
4289 bool
EmulateSTMDB(const uint32_t opcode,const ARMEncoding encoding)4290 EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
4291 {
4292 #if 0
4293 if ConditionPassed() then
4294 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4295 address = R[n] - 4*BitCount(registers);
4296
4297 for i = 0 to 14
4298 if registers<i> == '1' then
4299 if i == n && wback && i != LowestSetBit(registers) then
4300 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4301 else
4302 MemA[address,4] = R[i];
4303 address = address + 4;
4304
4305 if registers<15> == '1' then // Only possible for encoding A1
4306 MemA[address,4] = PCStoreValue();
4307
4308 if wback then R[n] = R[n] - 4*BitCount(registers);
4309 #endif
4310
4311
4312 bool success = false;
4313
4314 if (ConditionPassed(opcode))
4315 {
4316 uint32_t n;
4317 uint32_t registers = 0;
4318 bool wback;
4319 const uint32_t addr_byte_size = GetAddressByteSize();
4320
4321 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4322 switch (encoding)
4323 {
4324 case eEncodingT1:
4325 // if W == '1' && Rn == '1101' then SEE PUSH;
4326 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4327 {
4328 // See PUSH
4329 }
4330 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4331 n = Bits32 (opcode, 19, 16);
4332 registers = Bits32 (opcode, 15, 0);
4333 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4334 wback = BitIsSet (opcode, 21);
4335 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4336 if ((n == 15) || BitCount (registers) < 2)
4337 return false;
4338 // if wback && registers<n> == '1' then UNPREDICTABLE;
4339 if (wback && BitIsSet (registers, n))
4340 return false;
4341 break;
4342
4343 case eEncodingA1:
4344 // if W == '1' && Rn == '1101� && BitCount(register_list) >= 2 then SEE PUSH;
4345 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4346 {
4347 // See Push
4348 }
4349 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4350 n = Bits32 (opcode, 19, 16);
4351 registers = Bits32 (opcode, 15, 0);
4352 wback = BitIsSet (opcode, 21);
4353 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4354 if ((n == 15) || BitCount (registers) < 1)
4355 return false;
4356 break;
4357
4358 default:
4359 return false;
4360 }
4361
4362 // address = R[n] - 4*BitCount(registers);
4363
4364 int32_t offset = 0;
4365 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4366 if (!success)
4367 return false;
4368
4369 addr_t address = Rn - (addr_byte_size * BitCount (registers));
4370
4371 EmulateInstruction::Context context;
4372 context.type = EmulateInstruction::eContextRegisterStore;
4373 RegisterInfo base_reg;
4374 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4375
4376 // for i = 0 to 14
4377 uint32_t lowest_set_bit = 14;
4378 for (uint32_t i = 0; i < 14; ++i)
4379 {
4380 // if registers<i> == '1' then
4381 if (BitIsSet (registers, i))
4382 {
4383 if (i < lowest_set_bit)
4384 lowest_set_bit = i;
4385 // if i == n && wback && i != LowestSetBit(registers) then
4386 if ((i == n) && wback && (i != lowest_set_bit))
4387 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4388 WriteBits32UnknownToMemory (address + offset);
4389 else
4390 {
4391 // MemA[address,4] = R[i];
4392 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4393 if (!success)
4394 return false;
4395
4396 RegisterInfo data_reg;
4397 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4398 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4399 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4400 return false;
4401 }
4402
4403 // address = address + 4;
4404 offset += addr_byte_size;
4405 }
4406 }
4407
4408 // if registers<15> == '1' then // Only possible for encoding A1
4409 // MemA[address,4] = PCStoreValue();
4410 if (BitIsSet (registers, 15))
4411 {
4412 RegisterInfo pc_reg;
4413 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4414 context.SetRegisterPlusOffset (pc_reg, 8);
4415 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4416 if (!success)
4417 return false;
4418
4419 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4420 return false;
4421 }
4422
4423 // if wback then R[n] = R[n] - 4*BitCount(registers);
4424 if (wback)
4425 {
4426 offset = (addr_byte_size * BitCount (registers)) * -1;
4427 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4428 context.SetImmediateSigned (offset);
4429 addr_t data = Rn + offset;
4430 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4431 return false;
4432 }
4433 }
4434 return true;
4435 }
4436
4437 // STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4438 // from a base register. The consecutive memory locations start just above this address, and the address of the last
4439 // of those locations can optionally be written back to the base register.
4440 bool
EmulateSTMIB(const uint32_t opcode,const ARMEncoding encoding)4441 EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
4442 {
4443 #if 0
4444 if ConditionPassed() then
4445 EncodingSpecificOperations();
4446 address = R[n] + 4;
4447
4448 for i = 0 to 14
4449 if registers<i> == '1' then
4450 if i == n && wback && i != LowestSetBit(registers) then
4451 MemA[address,4] = bits(32) UNKNOWN;
4452 else
4453 MemA[address,4] = R[i];
4454 address = address + 4;
4455
4456 if registers<15> == '1' then
4457 MemA[address,4] = PCStoreValue();
4458
4459 if wback then R[n] = R[n] + 4*BitCount(registers);
4460 #endif
4461
4462 bool success = false;
4463
4464 if (ConditionPassed(opcode))
4465 {
4466 uint32_t n;
4467 uint32_t registers = 0;
4468 bool wback;
4469 const uint32_t addr_byte_size = GetAddressByteSize();
4470
4471 // EncodingSpecificOperations();
4472 switch (encoding)
4473 {
4474 case eEncodingA1:
4475 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4476 n = Bits32 (opcode, 19, 16);
4477 registers = Bits32 (opcode, 15, 0);
4478 wback = BitIsSet (opcode, 21);
4479
4480 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4481 if ((n == 15) && (BitCount (registers) < 1))
4482 return false;
4483 break;
4484 default:
4485 return false;
4486 }
4487 // address = R[n] + 4;
4488
4489 int32_t offset = 0;
4490 addr_t Rn = ReadCoreReg (n, &success);
4491 if (!success)
4492 return false;
4493
4494 addr_t address = Rn + addr_byte_size;
4495
4496 EmulateInstruction::Context context;
4497 context.type = EmulateInstruction::eContextRegisterStore;
4498 RegisterInfo base_reg;
4499 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4500
4501 uint32_t lowest_set_bit = 14;
4502 // for i = 0 to 14
4503 for (uint32_t i = 0; i < 14; ++i)
4504 {
4505 // if registers<i> == '1' then
4506 if (BitIsSet (registers, i))
4507 {
4508 if (i < lowest_set_bit)
4509 lowest_set_bit = i;
4510 // if i == n && wback && i != LowestSetBit(registers) then
4511 if ((i == n) && wback && (i != lowest_set_bit))
4512 // MemA[address,4] = bits(32) UNKNOWN;
4513 WriteBits32UnknownToMemory (address + offset);
4514 // else
4515 else
4516 {
4517 // MemA[address,4] = R[i];
4518 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4519 if (!success)
4520 return false;
4521
4522 RegisterInfo data_reg;
4523 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
4524 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
4525 if (!MemAWrite (context, address + offset, data, addr_byte_size))
4526 return false;
4527 }
4528
4529 // address = address + 4;
4530 offset += addr_byte_size;
4531 }
4532 }
4533
4534 // if registers<15> == '1' then
4535 // MemA[address,4] = PCStoreValue();
4536 if (BitIsSet (registers, 15))
4537 {
4538 RegisterInfo pc_reg;
4539 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
4540 context.SetRegisterPlusOffset (pc_reg, 8);
4541 const uint32_t pc = ReadCoreReg (PC_REG, &success);
4542 if (!success)
4543 return false;
4544
4545 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4546 return false;
4547 }
4548
4549 // if wback then R[n] = R[n] + 4*BitCount(registers);
4550 if (wback)
4551 {
4552 offset = addr_byte_size * BitCount (registers);
4553 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4554 context.SetImmediateSigned (offset);
4555 addr_t data = Rn + offset;
4556 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4557 return false;
4558 }
4559 }
4560 return true;
4561 }
4562
4563 // STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4564 // from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4565 bool
EmulateSTRThumb(const uint32_t opcode,const ARMEncoding encoding)4566 EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
4567 {
4568 #if 0
4569 if ConditionPassed() then
4570 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4571 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4572 address = if index then offset_addr else R[n];
4573 if UnalignedSupport() || address<1:0> == '00' then
4574 MemU[address,4] = R[t];
4575 else // Can only occur before ARMv7
4576 MemU[address,4] = bits(32) UNKNOWN;
4577 if wback then R[n] = offset_addr;
4578 #endif
4579
4580 bool success = false;
4581
4582 if (ConditionPassed(opcode))
4583 {
4584 const uint32_t addr_byte_size = GetAddressByteSize();
4585
4586 uint32_t t;
4587 uint32_t n;
4588 uint32_t imm32;
4589 bool index;
4590 bool add;
4591 bool wback;
4592 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4593 switch (encoding)
4594 {
4595 case eEncodingT1:
4596 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
4597 t = Bits32 (opcode, 2, 0);
4598 n = Bits32 (opcode, 5, 3);
4599 imm32 = Bits32 (opcode, 10, 6) << 2;
4600
4601 // index = TRUE; add = TRUE; wback = FALSE;
4602 index = true;
4603 add = false;
4604 wback = false;
4605 break;
4606
4607 case eEncodingT2:
4608 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4609 t = Bits32 (opcode, 10, 8);
4610 n = 13;
4611 imm32 = Bits32 (opcode, 7, 0) << 2;
4612
4613 // index = TRUE; add = TRUE; wback = FALSE;
4614 index = true;
4615 add = true;
4616 wback = false;
4617 break;
4618
4619 case eEncodingT3:
4620 // if Rn == '1111' then UNDEFINED;
4621 if (Bits32 (opcode, 19, 16) == 15)
4622 return false;
4623
4624 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4625 t = Bits32 (opcode, 15, 12);
4626 n = Bits32 (opcode, 19, 16);
4627 imm32 = Bits32 (opcode, 11, 0);
4628
4629 // index = TRUE; add = TRUE; wback = FALSE;
4630 index = true;
4631 add = true;
4632 wback = false;
4633
4634 // if t == 15 then UNPREDICTABLE;
4635 if (t == 15)
4636 return false;
4637 break;
4638
4639 case eEncodingT4:
4640 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4641 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4642 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
4643 if ((Bits32 (opcode, 19, 16) == 15)
4644 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4645 return false;
4646
4647 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4648 t = Bits32 (opcode, 15, 12);
4649 n = Bits32 (opcode, 19, 16);
4650 imm32 = Bits32 (opcode, 7, 0);
4651
4652 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4653 index = BitIsSet (opcode, 10);
4654 add = BitIsSet (opcode, 9);
4655 wback = BitIsSet (opcode, 8);
4656
4657 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4658 if ((t == 15) || (wback && (n == t)))
4659 return false;
4660 break;
4661
4662 default:
4663 return false;
4664 }
4665
4666 addr_t offset_addr;
4667 addr_t address;
4668
4669 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4670 uint32_t base_address = ReadCoreReg (n, &success);
4671 if (!success)
4672 return false;
4673
4674 if (add)
4675 offset_addr = base_address + imm32;
4676 else
4677 offset_addr = base_address - imm32;
4678
4679 // address = if index then offset_addr else R[n];
4680 if (index)
4681 address = offset_addr;
4682 else
4683 address = base_address;
4684
4685 EmulateInstruction::Context context;
4686 context.type = eContextRegisterStore;
4687 RegisterInfo base_reg;
4688 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4689
4690 // if UnalignedSupport() || address<1:0> == '00' then
4691 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4692 {
4693 // MemU[address,4] = R[t];
4694 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4695 if (!success)
4696 return false;
4697
4698 RegisterInfo data_reg;
4699 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4700 int32_t offset = address - base_address;
4701 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
4702 if (!MemUWrite (context, address, data, addr_byte_size))
4703 return false;
4704 }
4705 else
4706 {
4707 // MemU[address,4] = bits(32) UNKNOWN;
4708 WriteBits32UnknownToMemory (address);
4709 }
4710
4711 // if wback then R[n] = offset_addr;
4712 if (wback)
4713 {
4714 context.type = eContextRegisterLoad;
4715 context.SetAddress (offset_addr);
4716 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4717 return false;
4718 }
4719 }
4720 return true;
4721 }
4722
4723 // STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4724 // word from a register to memory. The offset register value can optionally be shifted.
4725 bool
EmulateSTRRegister(const uint32_t opcode,const ARMEncoding encoding)4726 EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
4727 {
4728 #if 0
4729 if ConditionPassed() then
4730 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4731 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4732 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4733 address = if index then offset_addr else R[n];
4734 if t == 15 then // Only possible for encoding A1
4735 data = PCStoreValue();
4736 else
4737 data = R[t];
4738 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
4739 MemU[address,4] = data;
4740 else // Can only occur before ARMv7
4741 MemU[address,4] = bits(32) UNKNOWN;
4742 if wback then R[n] = offset_addr;
4743 #endif
4744
4745 bool success = false;
4746
4747 if (ConditionPassed(opcode))
4748 {
4749 const uint32_t addr_byte_size = GetAddressByteSize();
4750
4751 uint32_t t;
4752 uint32_t n;
4753 uint32_t m;
4754 ARM_ShifterType shift_t;
4755 uint32_t shift_n;
4756 bool index;
4757 bool add;
4758 bool wback;
4759
4760 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4761 switch (encoding)
4762 {
4763 case eEncodingT1:
4764 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4765 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4766 t = Bits32 (opcode, 2, 0);
4767 n = Bits32 (opcode, 5, 3);
4768 m = Bits32 (opcode, 8, 6);
4769
4770 // index = TRUE; add = TRUE; wback = FALSE;
4771 index = true;
4772 add = true;
4773 wback = false;
4774
4775 // (shift_t, shift_n) = (SRType_LSL, 0);
4776 shift_t = SRType_LSL;
4777 shift_n = 0;
4778 break;
4779
4780 case eEncodingT2:
4781 // if Rn == '1111' then UNDEFINED;
4782 if (Bits32 (opcode, 19, 16) == 15)
4783 return false;
4784
4785 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4786 t = Bits32 (opcode, 15, 12);
4787 n = Bits32 (opcode, 19, 16);
4788 m = Bits32 (opcode, 3, 0);
4789
4790 // index = TRUE; add = TRUE; wback = FALSE;
4791 index = true;
4792 add = true;
4793 wback = false;
4794
4795 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4796 shift_t = SRType_LSL;
4797 shift_n = Bits32 (opcode, 5, 4);
4798
4799 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4800 if ((t == 15) || (BadReg (m)))
4801 return false;
4802 break;
4803
4804 case eEncodingA1:
4805 {
4806 // if P == '0' && W == '1' then SEE STRT;
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 typ = Bits32 (opcode, 6, 5);
4819 uint32_t imm5 = Bits32 (opcode, 11, 7);
4820 shift_n = DecodeImmShift(typ, 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 default:
4833 return false;
4834 }
4835
4836 addr_t offset_addr;
4837 addr_t address;
4838 int32_t offset = 0;
4839
4840 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4841 if (!success)
4842 return false;
4843
4844 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4845 if (!success)
4846 return false;
4847
4848 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4849 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4850 if (!success)
4851 return false;
4852
4853 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4854 if (add)
4855 offset_addr = base_address + offset;
4856 else
4857 offset_addr = base_address - offset;
4858
4859 // address = if index then offset_addr else R[n];
4860 if (index)
4861 address = offset_addr;
4862 else
4863 address = base_address;
4864
4865 uint32_t data;
4866 // if t == 15 then // Only possible for encoding A1
4867 if (t == 15)
4868 // data = PCStoreValue();
4869 data = ReadCoreReg (PC_REG, &success);
4870 else
4871 // data = R[t];
4872 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4873
4874 if (!success)
4875 return false;
4876
4877 EmulateInstruction::Context context;
4878 context.type = eContextRegisterStore;
4879
4880 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
4881 if (UnalignedSupport ()
4882 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4883 || CurrentInstrSet() == eModeARM)
4884 {
4885 // MemU[address,4] = data;
4886
4887 RegisterInfo base_reg;
4888 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
4889
4890 RegisterInfo data_reg;
4891 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
4892
4893 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4894 if (!MemUWrite (context, address, data, addr_byte_size))
4895 return false;
4896
4897 }
4898 else
4899 // MemU[address,4] = bits(32) UNKNOWN;
4900 WriteBits32UnknownToMemory (address);
4901
4902 // if wback then R[n] = offset_addr;
4903 if (wback)
4904 {
4905 context.type = eContextRegisterLoad;
4906 context.SetAddress (offset_addr);
4907 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4908 return false;
4909 }
4910
4911 }
4912 return true;
4913 }
4914
4915 bool
EmulateSTRBThumb(const uint32_t opcode,const ARMEncoding encoding)4916 EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
4917 {
4918 #if 0
4919 if ConditionPassed() then
4920 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4921 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4922 address = if index then offset_addr else R[n];
4923 MemU[address,1] = R[t]<7:0>;
4924 if wback then R[n] = offset_addr;
4925 #endif
4926
4927
4928 bool success = false;
4929
4930 if (ConditionPassed(opcode))
4931 {
4932 uint32_t t;
4933 uint32_t n;
4934 uint32_t imm32;
4935 bool index;
4936 bool add;
4937 bool wback;
4938 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4939 switch (encoding)
4940 {
4941 case eEncodingT1:
4942 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4943 t = Bits32 (opcode, 2, 0);
4944 n = Bits32 (opcode, 5, 3);
4945 imm32 = Bits32 (opcode, 10, 6);
4946
4947 // index = TRUE; add = TRUE; wback = FALSE;
4948 index = true;
4949 add = true;
4950 wback = false;
4951 break;
4952
4953 case eEncodingT2:
4954 // if Rn == '1111' then UNDEFINED;
4955 if (Bits32 (opcode, 19, 16) == 15)
4956 return false;
4957
4958 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4959 t = Bits32 (opcode, 15, 12);
4960 n = Bits32 (opcode, 19, 16);
4961 imm32 = Bits32 (opcode, 11, 0);
4962
4963 // index = TRUE; add = TRUE; wback = FALSE;
4964 index = true;
4965 add = true;
4966 wback = false;
4967
4968 // if BadReg(t) then UNPREDICTABLE;
4969 if (BadReg (t))
4970 return false;
4971 break;
4972
4973 case eEncodingT3:
4974 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4975 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
4976 if (Bits32 (opcode, 19, 16) == 15)
4977 return false;
4978
4979 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4980 t = Bits32 (opcode, 15, 12);
4981 n = Bits32 (opcode, 19, 16);
4982 imm32 = Bits32 (opcode, 7, 0);
4983
4984 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4985 index = BitIsSet (opcode, 10);
4986 add = BitIsSet (opcode, 9);
4987 wback = BitIsSet (opcode, 8);
4988
4989 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4990 if ((BadReg (t)) || (wback && (n == t)))
4991 return false;
4992 break;
4993
4994 default:
4995 return false;
4996 }
4997
4998 addr_t offset_addr;
4999 addr_t address;
5000 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5001 if (!success)
5002 return false;
5003
5004 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5005 if (add)
5006 offset_addr = base_address + imm32;
5007 else
5008 offset_addr = base_address - imm32;
5009
5010 // address = if index then offset_addr else R[n];
5011 if (index)
5012 address = offset_addr;
5013 else
5014 address = base_address;
5015
5016 // MemU[address,1] = R[t]<7:0>
5017 RegisterInfo base_reg;
5018 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5019
5020 RegisterInfo data_reg;
5021 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5022
5023 EmulateInstruction::Context context;
5024 context.type = eContextRegisterStore;
5025 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
5026
5027 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5028 if (!success)
5029 return false;
5030
5031 data = Bits32 (data, 7, 0);
5032
5033 if (!MemUWrite (context, address, data, 1))
5034 return false;
5035
5036 // if wback then R[n] = offset_addr;
5037 if (wback)
5038 {
5039 context.type = eContextRegisterLoad;
5040 context.SetAddress (offset_addr);
5041 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5042 return false;
5043 }
5044
5045 }
5046
5047 return true;
5048 }
5049
5050 // STRH (register) calculates an address from a base register value and an offset register value, and stores a
5051 // halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
5052 bool
EmulateSTRHRegister(const uint32_t opcode,const ARMEncoding encoding)5053 EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
5054 {
5055 #if 0
5056 if ConditionPassed() then
5057 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5058 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5059 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5060 address = if index then offset_addr else R[n];
5061 if UnalignedSupport() || address<0> == '0' then
5062 MemU[address,2] = R[t]<15:0>;
5063 else // Can only occur before ARMv7
5064 MemU[address,2] = bits(16) UNKNOWN;
5065 if wback then R[n] = offset_addr;
5066 #endif
5067
5068 bool success = false;
5069
5070 if (ConditionPassed(opcode))
5071 {
5072 uint32_t t;
5073 uint32_t n;
5074 uint32_t m;
5075 bool index;
5076 bool add;
5077 bool wback;
5078 ARM_ShifterType shift_t;
5079 uint32_t shift_n;
5080
5081 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5082 switch (encoding)
5083 {
5084 case eEncodingT1:
5085 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5086 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5087 t = Bits32 (opcode, 2, 0);
5088 n = Bits32 (opcode, 5, 3);
5089 m = Bits32 (opcode, 8, 6);
5090
5091 // index = TRUE; add = TRUE; wback = FALSE;
5092 index = true;
5093 add = true;
5094 wback = false;
5095
5096 // (shift_t, shift_n) = (SRType_LSL, 0);
5097 shift_t = SRType_LSL;
5098 shift_n = 0;
5099
5100 break;
5101
5102 case eEncodingT2:
5103 // if Rn == '1111' then UNDEFINED;
5104 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5105 t = Bits32 (opcode, 15, 12);
5106 n = Bits32 (opcode, 19, 16);
5107 m = Bits32 (opcode, 3, 0);
5108 if (n == 15)
5109 return false;
5110
5111 // index = TRUE; add = TRUE; wback = FALSE;
5112 index = true;
5113 add = true;
5114 wback = false;
5115
5116 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5117 shift_t = SRType_LSL;
5118 shift_n = Bits32 (opcode, 5, 4);
5119
5120 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5121 if (BadReg (t) || BadReg (m))
5122 return false;
5123
5124 break;
5125
5126 case eEncodingA1:
5127 // if P == '0' && W == '1' then SEE STRHT;
5128 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5129 t = Bits32 (opcode, 15, 12);
5130 n = Bits32 (opcode, 19, 16);
5131 m = Bits32 (opcode, 3, 0);
5132
5133 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5134 index = BitIsSet (opcode, 24);
5135 add = BitIsSet (opcode, 23);
5136 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5137
5138 // (shift_t, shift_n) = (SRType_LSL, 0);
5139 shift_t = SRType_LSL;
5140 shift_n = 0;
5141
5142 // if t == 15 || m == 15 then UNPREDICTABLE;
5143 if ((t == 15) || (m == 15))
5144 return false;
5145
5146 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5147 if (wback && ((n == 15) || (n == t)))
5148 return false;
5149
5150 break;
5151
5152 default:
5153 return false;
5154 }
5155
5156 uint32_t Rm = ReadCoreReg (m, &success);
5157 if (!success)
5158 return false;
5159
5160 uint32_t Rn = ReadCoreReg (n, &success);
5161 if (!success)
5162 return false;
5163
5164 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5165 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5166 if (!success)
5167 return false;
5168
5169 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5170 addr_t offset_addr;
5171 if (add)
5172 offset_addr = Rn + offset;
5173 else
5174 offset_addr = Rn - offset;
5175
5176 // address = if index then offset_addr else R[n];
5177 addr_t address;
5178 if (index)
5179 address = offset_addr;
5180 else
5181 address = Rn;
5182
5183 EmulateInstruction::Context context;
5184 context.type = eContextRegisterStore;
5185 RegisterInfo base_reg;
5186 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5187 RegisterInfo offset_reg;
5188 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5189
5190 // if UnalignedSupport() || address<0> == '0' then
5191 if (UnalignedSupport() || BitIsClear (address, 0))
5192 {
5193 // MemU[address,2] = R[t]<15:0>;
5194 uint32_t Rt = ReadCoreReg (t, &success);
5195 if (!success)
5196 return false;
5197
5198 EmulateInstruction::Context context;
5199 context.type = eContextRegisterStore;
5200 RegisterInfo base_reg;
5201 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5202 RegisterInfo offset_reg;
5203 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5204 RegisterInfo data_reg;
5205 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
5206 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5207
5208 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5209 return false;
5210 }
5211 else // Can only occur before ARMv7
5212 {
5213 // MemU[address,2] = bits(16) UNKNOWN;
5214 }
5215
5216 // if wback then R[n] = offset_addr;
5217 if (wback)
5218 {
5219 context.type = eContextAdjustBaseRegister;
5220 context.SetAddress (offset_addr);
5221 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5222 return false;
5223 }
5224 }
5225
5226 return true;
5227 }
5228
5229 // Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5230 // and writes the result to the destination register. It can optionally update the condition flags
5231 // based on the result.
5232 bool
EmulateADCImm(const uint32_t opcode,const ARMEncoding encoding)5233 EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
5234 {
5235 #if 0
5236 // ARM pseudo code...
5237 if ConditionPassed() then
5238 EncodingSpecificOperations();
5239 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5240 if d == 15 then // Can only occur for ARM encoding
5241 ALUWritePC(result); // setflags is always FALSE here
5242 else
5243 R[d] = result;
5244 if setflags then
5245 APSR.N = result<31>;
5246 APSR.Z = IsZeroBit(result);
5247 APSR.C = carry;
5248 APSR.V = overflow;
5249 #endif
5250
5251 bool success = false;
5252
5253 if (ConditionPassed(opcode))
5254 {
5255 uint32_t Rd, Rn;
5256 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5257 bool setflags;
5258 switch (encoding)
5259 {
5260 case eEncodingT1:
5261 Rd = Bits32(opcode, 11, 8);
5262 Rn = Bits32(opcode, 19, 16);
5263 setflags = BitIsSet(opcode, 20);
5264 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5265 if (BadReg(Rd) || BadReg(Rn))
5266 return false;
5267 break;
5268 case eEncodingA1:
5269 Rd = Bits32(opcode, 15, 12);
5270 Rn = Bits32(opcode, 19, 16);
5271 setflags = BitIsSet(opcode, 20);
5272 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5273
5274 if (Rd == 15 && setflags)
5275 return EmulateSUBSPcLrEtc (opcode, encoding);
5276 break;
5277 default:
5278 return false;
5279 }
5280
5281 // Read the first operand.
5282 int32_t val1 = ReadCoreReg(Rn, &success);
5283 if (!success)
5284 return false;
5285
5286 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5287
5288 EmulateInstruction::Context context;
5289 context.type = EmulateInstruction::eContextImmediate;
5290 context.SetNoArgs ();
5291
5292 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5293 return false;
5294 }
5295 return true;
5296 }
5297
5298 // Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5299 // register value, and writes the result to the destination register. It can optionally update the
5300 // condition flags based on the result.
5301 bool
EmulateADCReg(const uint32_t opcode,const ARMEncoding encoding)5302 EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
5303 {
5304 #if 0
5305 // ARM pseudo code...
5306 if ConditionPassed() then
5307 EncodingSpecificOperations();
5308 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5309 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5310 if d == 15 then // Can only occur for ARM encoding
5311 ALUWritePC(result); // setflags is always FALSE here
5312 else
5313 R[d] = result;
5314 if setflags then
5315 APSR.N = result<31>;
5316 APSR.Z = IsZeroBit(result);
5317 APSR.C = carry;
5318 APSR.V = overflow;
5319 #endif
5320
5321 bool success = false;
5322
5323 if (ConditionPassed(opcode))
5324 {
5325 uint32_t Rd, Rn, Rm;
5326 ARM_ShifterType shift_t;
5327 uint32_t shift_n; // the shift applied to the value read from Rm
5328 bool setflags;
5329 switch (encoding)
5330 {
5331 case eEncodingT1:
5332 Rd = Rn = Bits32(opcode, 2, 0);
5333 Rm = Bits32(opcode, 5, 3);
5334 setflags = !InITBlock();
5335 shift_t = SRType_LSL;
5336 shift_n = 0;
5337 break;
5338 case eEncodingT2:
5339 Rd = Bits32(opcode, 11, 8);
5340 Rn = Bits32(opcode, 19, 16);
5341 Rm = Bits32(opcode, 3, 0);
5342 setflags = BitIsSet(opcode, 20);
5343 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5344 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5345 return false;
5346 break;
5347 case eEncodingA1:
5348 Rd = Bits32(opcode, 15, 12);
5349 Rn = Bits32(opcode, 19, 16);
5350 Rm = Bits32(opcode, 3, 0);
5351 setflags = BitIsSet(opcode, 20);
5352 shift_n = DecodeImmShiftARM(opcode, shift_t);
5353
5354 if (Rd == 15 && setflags)
5355 return EmulateSUBSPcLrEtc (opcode, encoding);
5356 break;
5357 default:
5358 return false;
5359 }
5360
5361 // Read the first operand.
5362 int32_t val1 = ReadCoreReg(Rn, &success);
5363 if (!success)
5364 return false;
5365
5366 // Read the second operand.
5367 int32_t val2 = ReadCoreReg(Rm, &success);
5368 if (!success)
5369 return false;
5370
5371 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5372 if (!success)
5373 return false;
5374 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5375
5376 EmulateInstruction::Context context;
5377 context.type = EmulateInstruction::eContextImmediate;
5378 context.SetNoArgs ();
5379
5380 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5381 return false;
5382 }
5383 return true;
5384 }
5385
5386 // This instruction adds an immediate value to the PC value to form a PC-relative address,
5387 // and writes the result to the destination register.
5388 bool
EmulateADR(const uint32_t opcode,const ARMEncoding encoding)5389 EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
5390 {
5391 #if 0
5392 // ARM pseudo code...
5393 if ConditionPassed() then
5394 EncodingSpecificOperations();
5395 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5396 if d == 15 then // Can only occur for ARM encodings
5397 ALUWritePC(result);
5398 else
5399 R[d] = result;
5400 #endif
5401
5402 bool success = false;
5403
5404 if (ConditionPassed(opcode))
5405 {
5406 uint32_t Rd;
5407 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5408 bool add;
5409 switch (encoding)
5410 {
5411 case eEncodingT1:
5412 Rd = Bits32(opcode, 10, 8);
5413 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5414 add = true;
5415 break;
5416 case eEncodingT2:
5417 case eEncodingT3:
5418 Rd = Bits32(opcode, 11, 8);
5419 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5420 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5421 if (BadReg(Rd))
5422 return false;
5423 break;
5424 case eEncodingA1:
5425 case eEncodingA2:
5426 Rd = Bits32(opcode, 15, 12);
5427 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5428 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5429 break;
5430 default:
5431 return false;
5432 }
5433
5434 // Read the PC value.
5435 uint32_t pc = ReadCoreReg(PC_REG, &success);
5436 if (!success)
5437 return false;
5438
5439 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5440
5441 EmulateInstruction::Context context;
5442 context.type = EmulateInstruction::eContextImmediate;
5443 context.SetNoArgs ();
5444
5445 if (!WriteCoreReg(context, result, Rd))
5446 return false;
5447 }
5448 return true;
5449 }
5450
5451 // This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5452 // to the destination register. It can optionally update the condition flags based on the result.
5453 bool
EmulateANDImm(const uint32_t opcode,const ARMEncoding encoding)5454 EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
5455 {
5456 #if 0
5457 // ARM pseudo code...
5458 if ConditionPassed() then
5459 EncodingSpecificOperations();
5460 result = R[n] AND imm32;
5461 if d == 15 then // Can only occur for ARM encoding
5462 ALUWritePC(result); // setflags is always FALSE here
5463 else
5464 R[d] = result;
5465 if setflags then
5466 APSR.N = result<31>;
5467 APSR.Z = IsZeroBit(result);
5468 APSR.C = carry;
5469 // APSR.V unchanged
5470 #endif
5471
5472 bool success = false;
5473
5474 if (ConditionPassed(opcode))
5475 {
5476 uint32_t Rd, Rn;
5477 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5478 bool setflags;
5479 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5480 switch (encoding)
5481 {
5482 case eEncodingT1:
5483 Rd = Bits32(opcode, 11, 8);
5484 Rn = Bits32(opcode, 19, 16);
5485 setflags = BitIsSet(opcode, 20);
5486 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5487 // if Rd == '1111' && S == '1' then SEE TST (immediate);
5488 if (Rd == 15 && setflags)
5489 return EmulateTSTImm(opcode, eEncodingT1);
5490 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5491 return false;
5492 break;
5493 case eEncodingA1:
5494 Rd = Bits32(opcode, 15, 12);
5495 Rn = Bits32(opcode, 19, 16);
5496 setflags = BitIsSet(opcode, 20);
5497 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5498
5499 if (Rd == 15 && setflags)
5500 return EmulateSUBSPcLrEtc (opcode, encoding);
5501 break;
5502 default:
5503 return false;
5504 }
5505
5506 // Read the first operand.
5507 uint32_t val1 = ReadCoreReg(Rn, &success);
5508 if (!success)
5509 return false;
5510
5511 uint32_t result = val1 & imm32;
5512
5513 EmulateInstruction::Context context;
5514 context.type = EmulateInstruction::eContextImmediate;
5515 context.SetNoArgs ();
5516
5517 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5518 return false;
5519 }
5520 return true;
5521 }
5522
5523 // This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5524 // and writes the result to the destination register. It can optionally update the condition flags
5525 // based on the result.
5526 bool
EmulateANDReg(const uint32_t opcode,const ARMEncoding encoding)5527 EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
5528 {
5529 #if 0
5530 // ARM pseudo code...
5531 if ConditionPassed() then
5532 EncodingSpecificOperations();
5533 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5534 result = R[n] AND shifted;
5535 if d == 15 then // Can only occur for ARM encoding
5536 ALUWritePC(result); // setflags is always FALSE here
5537 else
5538 R[d] = result;
5539 if setflags then
5540 APSR.N = result<31>;
5541 APSR.Z = IsZeroBit(result);
5542 APSR.C = carry;
5543 // APSR.V unchanged
5544 #endif
5545
5546 bool success = false;
5547
5548 if (ConditionPassed(opcode))
5549 {
5550 uint32_t Rd, Rn, Rm;
5551 ARM_ShifterType shift_t;
5552 uint32_t shift_n; // the shift applied to the value read from Rm
5553 bool setflags;
5554 uint32_t carry;
5555 switch (encoding)
5556 {
5557 case eEncodingT1:
5558 Rd = Rn = Bits32(opcode, 2, 0);
5559 Rm = Bits32(opcode, 5, 3);
5560 setflags = !InITBlock();
5561 shift_t = SRType_LSL;
5562 shift_n = 0;
5563 break;
5564 case eEncodingT2:
5565 Rd = Bits32(opcode, 11, 8);
5566 Rn = Bits32(opcode, 19, 16);
5567 Rm = Bits32(opcode, 3, 0);
5568 setflags = BitIsSet(opcode, 20);
5569 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5570 // if Rd == '1111' && S == '1' then SEE TST (register);
5571 if (Rd == 15 && setflags)
5572 return EmulateTSTReg(opcode, eEncodingT2);
5573 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5574 return false;
5575 break;
5576 case eEncodingA1:
5577 Rd = Bits32(opcode, 15, 12);
5578 Rn = Bits32(opcode, 19, 16);
5579 Rm = Bits32(opcode, 3, 0);
5580 setflags = BitIsSet(opcode, 20);
5581 shift_n = DecodeImmShiftARM(opcode, shift_t);
5582
5583 if (Rd == 15 && setflags)
5584 return EmulateSUBSPcLrEtc (opcode, encoding);
5585 break;
5586 default:
5587 return false;
5588 }
5589
5590 // Read the first operand.
5591 uint32_t val1 = ReadCoreReg(Rn, &success);
5592 if (!success)
5593 return false;
5594
5595 // Read the second operand.
5596 uint32_t val2 = ReadCoreReg(Rm, &success);
5597 if (!success)
5598 return false;
5599
5600 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5601 if (!success)
5602 return false;
5603 uint32_t result = val1 & shifted;
5604
5605 EmulateInstruction::Context context;
5606 context.type = EmulateInstruction::eContextImmediate;
5607 context.SetNoArgs ();
5608
5609 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5610 return false;
5611 }
5612 return true;
5613 }
5614
5615 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5616 // immediate value, and writes the result to the destination register. It can optionally update the
5617 // condition flags based on the result.
5618 bool
EmulateBICImm(const uint32_t opcode,const ARMEncoding encoding)5619 EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
5620 {
5621 #if 0
5622 // ARM pseudo code...
5623 if ConditionPassed() then
5624 EncodingSpecificOperations();
5625 result = R[n] AND NOT(imm32);
5626 if d == 15 then // Can only occur for ARM encoding
5627 ALUWritePC(result); // setflags is always FALSE here
5628 else
5629 R[d] = result;
5630 if setflags then
5631 APSR.N = result<31>;
5632 APSR.Z = IsZeroBit(result);
5633 APSR.C = carry;
5634 // APSR.V unchanged
5635 #endif
5636
5637 bool success = false;
5638
5639 if (ConditionPassed(opcode))
5640 {
5641 uint32_t Rd, Rn;
5642 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5643 bool setflags;
5644 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5645 switch (encoding)
5646 {
5647 case eEncodingT1:
5648 Rd = Bits32(opcode, 11, 8);
5649 Rn = Bits32(opcode, 19, 16);
5650 setflags = BitIsSet(opcode, 20);
5651 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5652 if (BadReg(Rd) || BadReg(Rn))
5653 return false;
5654 break;
5655 case eEncodingA1:
5656 Rd = Bits32(opcode, 15, 12);
5657 Rn = Bits32(opcode, 19, 16);
5658 setflags = BitIsSet(opcode, 20);
5659 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5660
5661 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5662 if (Rd == 15 && setflags)
5663 return EmulateSUBSPcLrEtc (opcode, encoding);
5664 break;
5665 default:
5666 return false;
5667 }
5668
5669 // Read the first operand.
5670 uint32_t val1 = ReadCoreReg(Rn, &success);
5671 if (!success)
5672 return false;
5673
5674 uint32_t result = val1 & ~imm32;
5675
5676 EmulateInstruction::Context context;
5677 context.type = EmulateInstruction::eContextImmediate;
5678 context.SetNoArgs ();
5679
5680 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5681 return false;
5682 }
5683 return true;
5684 }
5685
5686 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5687 // optionally-shifted register value, and writes the result to the destination register.
5688 // It can optionally update the condition flags based on the result.
5689 bool
EmulateBICReg(const uint32_t opcode,const ARMEncoding encoding)5690 EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
5691 {
5692 #if 0
5693 // ARM pseudo code...
5694 if ConditionPassed() then
5695 EncodingSpecificOperations();
5696 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5697 result = R[n] AND NOT(shifted);
5698 if d == 15 then // Can only occur for ARM encoding
5699 ALUWritePC(result); // setflags is always FALSE here
5700 else
5701 R[d] = result;
5702 if setflags then
5703 APSR.N = result<31>;
5704 APSR.Z = IsZeroBit(result);
5705 APSR.C = carry;
5706 // APSR.V unchanged
5707 #endif
5708
5709 bool success = false;
5710
5711 if (ConditionPassed(opcode))
5712 {
5713 uint32_t Rd, Rn, Rm;
5714 ARM_ShifterType shift_t;
5715 uint32_t shift_n; // the shift applied to the value read from Rm
5716 bool setflags;
5717 uint32_t carry;
5718 switch (encoding)
5719 {
5720 case eEncodingT1:
5721 Rd = Rn = Bits32(opcode, 2, 0);
5722 Rm = Bits32(opcode, 5, 3);
5723 setflags = !InITBlock();
5724 shift_t = SRType_LSL;
5725 shift_n = 0;
5726 break;
5727 case eEncodingT2:
5728 Rd = Bits32(opcode, 11, 8);
5729 Rn = Bits32(opcode, 19, 16);
5730 Rm = Bits32(opcode, 3, 0);
5731 setflags = BitIsSet(opcode, 20);
5732 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5733 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5734 return false;
5735 break;
5736 case eEncodingA1:
5737 Rd = Bits32(opcode, 15, 12);
5738 Rn = Bits32(opcode, 19, 16);
5739 Rm = Bits32(opcode, 3, 0);
5740 setflags = BitIsSet(opcode, 20);
5741 shift_n = DecodeImmShiftARM(opcode, shift_t);
5742
5743 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5744 if (Rd == 15 && setflags)
5745 return EmulateSUBSPcLrEtc (opcode, encoding);
5746 break;
5747 default:
5748 return false;
5749 }
5750
5751 // Read the first operand.
5752 uint32_t val1 = ReadCoreReg(Rn, &success);
5753 if (!success)
5754 return false;
5755
5756 // Read the second operand.
5757 uint32_t val2 = ReadCoreReg(Rm, &success);
5758 if (!success)
5759 return false;
5760
5761 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5762 if (!success)
5763 return false;
5764 uint32_t result = val1 & ~shifted;
5765
5766 EmulateInstruction::Context context;
5767 context.type = EmulateInstruction::eContextImmediate;
5768 context.SetNoArgs ();
5769
5770 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5771 return false;
5772 }
5773 return true;
5774 }
5775
5776 // LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
5777 // from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing.
5778 bool
EmulateLDRImmediateARM(const uint32_t opcode,const ARMEncoding encoding)5779 EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
5780 {
5781 #if 0
5782 if ConditionPassed() then
5783 EncodingSpecificOperations();
5784 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5785 address = if index then offset_addr else R[n];
5786 data = MemU[address,4];
5787 if wback then R[n] = offset_addr;
5788 if t == 15 then
5789 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5790 elsif UnalignedSupport() || address<1:0> = '00' then
5791 R[t] = data;
5792 else // Can only apply before ARMv7
5793 R[t] = ROR(data, 8*UInt(address<1:0>));
5794 #endif
5795
5796 bool success = false;
5797
5798 if (ConditionPassed(opcode))
5799 {
5800 const uint32_t addr_byte_size = GetAddressByteSize();
5801
5802 uint32_t t;
5803 uint32_t n;
5804 uint32_t imm32;
5805 bool index;
5806 bool add;
5807 bool wback;
5808
5809 switch (encoding)
5810 {
5811 case eEncodingA1:
5812 // if Rn == '1111' then SEE LDR (literal);
5813 // if P == '0' && W == '1' then SEE LDRT;
5814 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
5815 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5816 t = Bits32 (opcode, 15, 12);
5817 n = Bits32 (opcode, 19, 16);
5818 imm32 = Bits32 (opcode, 11, 0);
5819
5820 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5821 index = BitIsSet (opcode, 24);
5822 add = BitIsSet (opcode, 23);
5823 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5824
5825 // if wback && n == t then UNPREDICTABLE;
5826 if (wback && (n == t))
5827 return false;
5828
5829 break;
5830
5831 default:
5832 return false;
5833 }
5834
5835 addr_t address;
5836 addr_t offset_addr;
5837 addr_t base_address = ReadCoreReg (n, &success);
5838 if (!success)
5839 return false;
5840
5841 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5842 if (add)
5843 offset_addr = base_address + imm32;
5844 else
5845 offset_addr = base_address - imm32;
5846
5847 // address = if index then offset_addr else R[n];
5848 if (index)
5849 address = offset_addr;
5850 else
5851 address = base_address;
5852
5853 // data = MemU[address,4];
5854
5855 RegisterInfo base_reg;
5856 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5857
5858 EmulateInstruction::Context context;
5859 context.type = eContextRegisterLoad;
5860 context.SetRegisterPlusOffset (base_reg, address - base_address);
5861
5862 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5863 if (!success)
5864 return false;
5865
5866 // if wback then R[n] = offset_addr;
5867 if (wback)
5868 {
5869 context.type = eContextAdjustBaseRegister;
5870 context.SetAddress (offset_addr);
5871 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5872 return false;
5873 }
5874
5875 // if t == 15 then
5876 if (t == 15)
5877 {
5878 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5879 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5880 {
5881 // LoadWritePC (data);
5882 context.type = eContextRegisterLoad;
5883 context.SetRegisterPlusOffset (base_reg, address - base_address);
5884 LoadWritePC (context, data);
5885 }
5886 else
5887 return false;
5888 }
5889 // elsif UnalignedSupport() || address<1:0> = '00' then
5890 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5891 {
5892 // R[t] = data;
5893 context.type = eContextRegisterLoad;
5894 context.SetRegisterPlusOffset (base_reg, address - base_address);
5895 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5896 return false;
5897 }
5898 // else // Can only apply before ARMv7
5899 else
5900 {
5901 // R[t] = ROR(data, 8*UInt(address<1:0>));
5902 data = ROR (data, Bits32 (address, 1, 0), &success);
5903 if (!success)
5904 return false;
5905 context.type = eContextRegisterLoad;
5906 context.SetImmediate (data);
5907 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5908 return false;
5909 }
5910
5911 }
5912 return true;
5913 }
5914
5915 // LDR (register) calculates an address from a base register value and an offset register value, loads a word
5916 // from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5917 bool
EmulateLDRRegister(const uint32_t opcode,const ARMEncoding encoding)5918 EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
5919 {
5920 #if 0
5921 if ConditionPassed() then
5922 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5923 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5924 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5925 address = if index then offset_addr else R[n];
5926 data = MemU[address,4];
5927 if wback then R[n] = offset_addr;
5928 if t == 15 then
5929 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5930 elsif UnalignedSupport() || address<1:0> = '00' then
5931 R[t] = data;
5932 else // Can only apply before ARMv7
5933 if CurrentInstrSet() == InstrSet_ARM then
5934 R[t] = ROR(data, 8*UInt(address<1:0>));
5935 else
5936 R[t] = bits(32) UNKNOWN;
5937 #endif
5938
5939 bool success = false;
5940
5941 if (ConditionPassed(opcode))
5942 {
5943 const uint32_t addr_byte_size = GetAddressByteSize();
5944
5945 uint32_t t;
5946 uint32_t n;
5947 uint32_t m;
5948 bool index;
5949 bool add;
5950 bool wback;
5951 ARM_ShifterType shift_t;
5952 uint32_t shift_n;
5953
5954 switch (encoding)
5955 {
5956 case eEncodingT1:
5957 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5958 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5959 t = Bits32 (opcode, 2, 0);
5960 n = Bits32 (opcode, 5, 3);
5961 m = Bits32 (opcode, 8, 6);
5962
5963 // index = TRUE; add = TRUE; wback = FALSE;
5964 index = true;
5965 add = true;
5966 wback = false;
5967
5968 // (shift_t, shift_n) = (SRType_LSL, 0);
5969 shift_t = SRType_LSL;
5970 shift_n = 0;
5971
5972 break;
5973
5974 case eEncodingT2:
5975 // if Rn == '1111' then SEE LDR (literal);
5976 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5977 t = Bits32 (opcode, 15, 12);
5978 n = Bits32 (opcode, 19, 16);
5979 m = Bits32 (opcode, 3, 0);
5980
5981 // index = TRUE; add = TRUE; wback = FALSE;
5982 index = true;
5983 add = true;
5984 wback = false;
5985
5986 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5987 shift_t = SRType_LSL;
5988 shift_n = Bits32 (opcode, 5, 4);
5989
5990 // if BadReg(m) then UNPREDICTABLE;
5991 if (BadReg (m))
5992 return false;
5993
5994 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5995 if ((t == 15) && InITBlock() && !LastInITBlock())
5996 return false;
5997
5998 break;
5999
6000 case eEncodingA1:
6001 {
6002 // if P == '0' && W == '1' then SEE LDRT;
6003 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6004 t = Bits32 (opcode, 15, 12);
6005 n = Bits32 (opcode, 19, 16);
6006 m = Bits32 (opcode, 3, 0);
6007
6008 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6009 index = BitIsSet (opcode, 24);
6010 add = BitIsSet (opcode, 23);
6011 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6012
6013 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6014 uint32_t type = Bits32 (opcode, 6, 5);
6015 uint32_t imm5 = Bits32 (opcode, 11, 7);
6016 shift_n = DecodeImmShift (type, imm5, shift_t);
6017
6018 // if m == 15 then UNPREDICTABLE;
6019 if (m == 15)
6020 return false;
6021
6022 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6023 if (wback && ((n == 15) || (n == t)))
6024 return false;
6025 }
6026 break;
6027
6028
6029 default:
6030 return false;
6031 }
6032
6033 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6034 if (!success)
6035 return false;
6036
6037 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6038 if (!success)
6039 return false;
6040
6041 addr_t offset_addr;
6042 addr_t address;
6043
6044 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
6045 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
6046 if (!success)
6047 return false;
6048
6049 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6050 if (add)
6051 offset_addr = Rn + offset;
6052 else
6053 offset_addr = Rn - offset;
6054
6055 // address = if index then offset_addr else R[n];
6056 if (index)
6057 address = offset_addr;
6058 else
6059 address = Rn;
6060
6061 // data = MemU[address,4];
6062 RegisterInfo base_reg;
6063 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6064
6065 EmulateInstruction::Context context;
6066 context.type = eContextRegisterLoad;
6067 context.SetRegisterPlusOffset (base_reg, address - Rn);
6068
6069 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6070 if (!success)
6071 return false;
6072
6073 // if wback then R[n] = offset_addr;
6074 if (wback)
6075 {
6076 context.type = eContextAdjustBaseRegister;
6077 context.SetAddress (offset_addr);
6078 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6079 return false;
6080 }
6081
6082 // if t == 15 then
6083 if (t == 15)
6084 {
6085 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6086 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6087 {
6088 context.type = eContextRegisterLoad;
6089 context.SetRegisterPlusOffset (base_reg, address - Rn);
6090 LoadWritePC (context, data);
6091 }
6092 else
6093 return false;
6094 }
6095 // elsif UnalignedSupport() || address<1:0> = '00' then
6096 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6097 {
6098 // R[t] = data;
6099 context.type = eContextRegisterLoad;
6100 context.SetRegisterPlusOffset (base_reg, address - Rn);
6101 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6102 return false;
6103 }
6104 else // Can only apply before ARMv7
6105 {
6106 // if CurrentInstrSet() == InstrSet_ARM then
6107 if (CurrentInstrSet () == eModeARM)
6108 {
6109 // R[t] = ROR(data, 8*UInt(address<1:0>));
6110 data = ROR (data, Bits32 (address, 1, 0), &success);
6111 if (!success)
6112 return false;
6113 context.type = eContextRegisterLoad;
6114 context.SetImmediate (data);
6115 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6116 return false;
6117 }
6118 else
6119 {
6120 // R[t] = bits(32) UNKNOWN;
6121 WriteBits32Unknown (t);
6122 }
6123 }
6124 }
6125 return true;
6126 }
6127
6128 // LDRB (immediate, Thumb)
6129 bool
EmulateLDRBImmediate(const uint32_t opcode,const ARMEncoding encoding)6130 EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
6131 {
6132 #if 0
6133 if ConditionPassed() then
6134 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6135 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6136 address = if index then offset_addr else R[n];
6137 R[t] = ZeroExtend(MemU[address,1], 32);
6138 if wback then R[n] = offset_addr;
6139 #endif
6140
6141 bool success = false;
6142
6143 if (ConditionPassed(opcode))
6144 {
6145 uint32_t t;
6146 uint32_t n;
6147 uint32_t imm32;
6148 bool index;
6149 bool add;
6150 bool wback;
6151
6152 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6153 switch (encoding)
6154 {
6155 case eEncodingT1:
6156 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6157 t = Bits32 (opcode, 2, 0);
6158 n = Bits32 (opcode, 5, 3);
6159 imm32 = Bits32 (opcode, 10, 6);
6160
6161 // index = TRUE; add = TRUE; wback = FALSE;
6162 index = true;
6163 add = true;
6164 wback= false;
6165
6166 break;
6167
6168 case eEncodingT2:
6169 // if Rt == '1111' then SEE PLD;
6170 // if Rn == '1111' then SEE LDRB (literal);
6171 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6172 t = Bits32 (opcode, 15, 12);
6173 n = Bits32 (opcode, 19, 16);
6174 imm32 = Bits32 (opcode, 11, 0);
6175
6176 // index = TRUE; add = TRUE; wback = FALSE;
6177 index = true;
6178 add = true;
6179 wback = false;
6180
6181 // if t == 13 then UNPREDICTABLE;
6182 if (t == 13)
6183 return false;
6184
6185 break;
6186
6187 case eEncodingT3:
6188 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6189 // if Rn == '1111' then SEE LDRB (literal);
6190 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6191 // if P == '0' && W == '0' then UNDEFINED;
6192 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6193 return false;
6194
6195 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6196 t = Bits32 (opcode, 15, 12);
6197 n = Bits32 (opcode, 19, 16);
6198 imm32 = Bits32 (opcode, 7, 0);
6199
6200 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6201 index = BitIsSet (opcode, 10);
6202 add = BitIsSet (opcode, 9);
6203 wback = BitIsSet (opcode, 8);
6204
6205 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6206 if (BadReg (t) || (wback && (n == t)))
6207 return false;
6208
6209 break;
6210
6211 default:
6212 return false;
6213 }
6214
6215 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6216 if (!success)
6217 return false;
6218
6219 addr_t address;
6220 addr_t offset_addr;
6221
6222 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6223 if (add)
6224 offset_addr = Rn + imm32;
6225 else
6226 offset_addr = Rn - imm32;
6227
6228 // address = if index then offset_addr else R[n];
6229 if (index)
6230 address = offset_addr;
6231 else
6232 address = Rn;
6233
6234 // R[t] = ZeroExtend(MemU[address,1], 32);
6235 RegisterInfo base_reg;
6236 RegisterInfo data_reg;
6237 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6238 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
6239
6240 EmulateInstruction::Context context;
6241 context.type = eContextRegisterLoad;
6242 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6243
6244 uint64_t data = MemURead (context, address, 1, 0, &success);
6245 if (!success)
6246 return false;
6247
6248 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6249 return false;
6250
6251 // if wback then R[n] = offset_addr;
6252 if (wback)
6253 {
6254 context.type = eContextAdjustBaseRegister;
6255 context.SetAddress (offset_addr);
6256 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6257 return false;
6258 }
6259 }
6260 return true;
6261 }
6262
6263 // LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6264 // zero-extends it to form a 32-bit word and writes it to a register.
6265 bool
EmulateLDRBLiteral(const uint32_t opcode,const ARMEncoding encoding)6266 EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
6267 {
6268 #if 0
6269 if ConditionPassed() then
6270 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6271 base = Align(PC,4);
6272 address = if add then (base + imm32) else (base - imm32);
6273 R[t] = ZeroExtend(MemU[address,1], 32);
6274 #endif
6275
6276 bool success = false;
6277
6278 if (ConditionPassed(opcode))
6279 {
6280 uint32_t t;
6281 uint32_t imm32;
6282 bool add;
6283 switch (encoding)
6284 {
6285 case eEncodingT1:
6286 // if Rt == '1111' then SEE PLD;
6287 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6288 t = Bits32 (opcode, 15, 12);
6289 imm32 = Bits32 (opcode, 11, 0);
6290 add = BitIsSet (opcode, 23);
6291
6292 // if t == 13 then UNPREDICTABLE;
6293 if (t == 13)
6294 return false;
6295
6296 break;
6297
6298 case eEncodingA1:
6299 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6300 t = Bits32 (opcode, 15, 12);
6301 imm32 = Bits32 (opcode, 11, 0);
6302 add = BitIsSet (opcode, 23);
6303
6304 // if t == 15 then UNPREDICTABLE;
6305 if (t == 15)
6306 return false;
6307 break;
6308
6309 default:
6310 return false;
6311 }
6312
6313 // base = Align(PC,4);
6314 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
6315 if (!success)
6316 return false;
6317
6318 uint32_t base = AlignPC (pc_val);
6319
6320 addr_t address;
6321 // address = if add then (base + imm32) else (base - imm32);
6322 if (add)
6323 address = base + imm32;
6324 else
6325 address = base - imm32;
6326
6327 // R[t] = ZeroExtend(MemU[address,1], 32);
6328 EmulateInstruction::Context context;
6329 context.type = eContextRelativeBranchImmediate;
6330 context.SetImmediate (address - base);
6331
6332 uint64_t data = MemURead (context, address, 1, 0, &success);
6333 if (!success)
6334 return false;
6335
6336 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6337 return false;
6338 }
6339 return true;
6340 }
6341
6342 // LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6343 // memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6344 // optionally be shifted.
6345 bool
EmulateLDRBRegister(const uint32_t opcode,const ARMEncoding encoding)6346 EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
6347 {
6348 #if 0
6349 if ConditionPassed() then
6350 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6351 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6352 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6353 address = if index then offset_addr else R[n];
6354 R[t] = ZeroExtend(MemU[address,1],32);
6355 if wback then R[n] = offset_addr;
6356 #endif
6357
6358 bool success = false;
6359
6360 if (ConditionPassed(opcode))
6361 {
6362 uint32_t t;
6363 uint32_t n;
6364 uint32_t m;
6365 bool index;
6366 bool add;
6367 bool wback;
6368 ARM_ShifterType shift_t;
6369 uint32_t shift_n;
6370
6371 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6372 switch (encoding)
6373 {
6374 case eEncodingT1:
6375 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6376 t = Bits32 (opcode, 2, 0);
6377 n = Bits32 (opcode, 5, 3);
6378 m = Bits32 (opcode, 8, 6);
6379
6380 // index = TRUE; add = TRUE; wback = FALSE;
6381 index = true;
6382 add = true;
6383 wback = false;
6384
6385 // (shift_t, shift_n) = (SRType_LSL, 0);
6386 shift_t = SRType_LSL;
6387 shift_n = 0;
6388 break;
6389
6390 case eEncodingT2:
6391 // if Rt == '1111' then SEE PLD;
6392 // if Rn == '1111' then SEE LDRB (literal);
6393 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6394 t = Bits32 (opcode, 15, 12);
6395 n = Bits32 (opcode, 19, 16);
6396 m = Bits32 (opcode, 3, 0);
6397
6398 // index = TRUE; add = TRUE; wback = FALSE;
6399 index = true;
6400 add = true;
6401 wback = false;
6402
6403 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6404 shift_t = SRType_LSL;
6405 shift_n = Bits32 (opcode, 5, 4);
6406
6407 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6408 if ((t == 13) || BadReg (m))
6409 return false;
6410 break;
6411
6412 case eEncodingA1:
6413 {
6414 // if P == '0' && W == '1' then SEE LDRBT;
6415 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6416 t = Bits32 (opcode, 15, 12);
6417 n = Bits32 (opcode, 19, 16);
6418 m = Bits32 (opcode, 3, 0);
6419
6420 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6421 index = BitIsSet (opcode, 24);
6422 add = BitIsSet (opcode, 23);
6423 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6424
6425 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6426 uint32_t type = Bits32 (opcode, 6, 5);
6427 uint32_t imm5 = Bits32 (opcode, 11, 7);
6428 shift_n = DecodeImmShift (type, imm5, shift_t);
6429
6430 // if t == 15 || m == 15 then UNPREDICTABLE;
6431 if ((t == 15) || (m == 15))
6432 return false;
6433
6434 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6435 if (wback && ((n == 15) || (n == t)))
6436 return false;
6437 }
6438 break;
6439
6440 default:
6441 return false;
6442 }
6443
6444 addr_t offset_addr;
6445 addr_t address;
6446
6447 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6448 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6449 if (!success)
6450 return false;
6451
6452 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6453 if (!success)
6454 return false;
6455
6456 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6457 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6458 if (!success)
6459 return false;
6460
6461 if (add)
6462 offset_addr = Rn + offset;
6463 else
6464 offset_addr = Rn - offset;
6465
6466 // address = if index then offset_addr else R[n];
6467 if (index)
6468 address = offset_addr;
6469 else
6470 address = Rn;
6471
6472 // R[t] = ZeroExtend(MemU[address,1],32);
6473 RegisterInfo base_reg;
6474 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6475
6476 EmulateInstruction::Context context;
6477 context.type = eContextRegisterLoad;
6478 context.SetRegisterPlusOffset (base_reg, address - Rn);
6479
6480 uint64_t data = MemURead (context, address, 1, 0, &success);
6481 if (!success)
6482 return false;
6483
6484 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6485 return false;
6486
6487 // if wback then R[n] = offset_addr;
6488 if (wback)
6489 {
6490 context.type = eContextAdjustBaseRegister;
6491 context.SetAddress (offset_addr);
6492 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6493 return false;
6494 }
6495 }
6496 return true;
6497 }
6498
6499 // LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6500 // halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6501 // post-indexed, or pre-indexed addressing.
6502 bool
EmulateLDRHImmediate(const uint32_t opcode,const ARMEncoding encoding)6503 EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
6504 {
6505 #if 0
6506 if ConditionPassed() then
6507 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6508 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6509 address = if index then offset_addr else R[n];
6510 data = MemU[address,2];
6511 if wback then R[n] = offset_addr;
6512 if UnalignedSupport() || address<0> = '0' then
6513 R[t] = ZeroExtend(data, 32);
6514 else // Can only apply before ARMv7
6515 R[t] = bits(32) UNKNOWN;
6516 #endif
6517
6518
6519 bool success = false;
6520
6521 if (ConditionPassed(opcode))
6522 {
6523 uint32_t t;
6524 uint32_t n;
6525 uint32_t imm32;
6526 bool index;
6527 bool add;
6528 bool wback;
6529
6530 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6531 switch (encoding)
6532 {
6533 case eEncodingT1:
6534 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
6535 t = Bits32 (opcode, 2, 0);
6536 n = Bits32 (opcode, 5, 3);
6537 imm32 = Bits32 (opcode, 10, 6) << 1;
6538
6539 // index = TRUE; add = TRUE; wback = FALSE;
6540 index = true;
6541 add = true;
6542 wback = false;
6543
6544 break;
6545
6546 case eEncodingT2:
6547 // if Rt == '1111' then SEE "Unallocated memory hints";
6548 // if Rn == '1111' then SEE LDRH (literal);
6549 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6550 t = Bits32 (opcode, 15, 12);
6551 n = Bits32 (opcode, 19, 16);
6552 imm32 = Bits32 (opcode, 11, 0);
6553
6554 // index = TRUE; add = TRUE; wback = FALSE;
6555 index = true;
6556 add = true;
6557 wback = false;
6558
6559 // if t == 13 then UNPREDICTABLE;
6560 if (t == 13)
6561 return false;
6562 break;
6563
6564 case eEncodingT3:
6565 // if Rn == '1111' then SEE LDRH (literal);
6566 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6567 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6568 // if P == '0' && W == '0' then UNDEFINED;
6569 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6570 return false;
6571
6572 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6573 t = Bits32 (opcode, 15, 12);
6574 n = Bits32 (opcode, 19, 16);
6575 imm32 = Bits32 (opcode, 7, 0);
6576
6577 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6578 index = BitIsSet (opcode, 10);
6579 add = BitIsSet (opcode, 9);
6580 wback = BitIsSet (opcode, 8);
6581
6582 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6583 if (BadReg (t) || (wback && (n == t)))
6584 return false;
6585 break;
6586
6587 default:
6588 return false;
6589 }
6590
6591 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6592 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6593 if (!success)
6594 return false;
6595
6596 addr_t offset_addr;
6597 addr_t address;
6598
6599 if (add)
6600 offset_addr = Rn + imm32;
6601 else
6602 offset_addr = Rn - imm32;
6603
6604 // address = if index then offset_addr else R[n];
6605 if (index)
6606 address = offset_addr;
6607 else
6608 address = Rn;
6609
6610 // data = MemU[address,2];
6611 RegisterInfo base_reg;
6612 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6613
6614 EmulateInstruction::Context context;
6615 context.type = eContextRegisterLoad;
6616 context.SetRegisterPlusOffset (base_reg, address - Rn);
6617
6618 uint64_t data = MemURead (context, address, 2, 0, &success);
6619 if (!success)
6620 return false;
6621
6622 // if wback then R[n] = offset_addr;
6623 if (wback)
6624 {
6625 context.type = eContextAdjustBaseRegister;
6626 context.SetAddress (offset_addr);
6627 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6628 return false;
6629 }
6630
6631 // if UnalignedSupport() || address<0> = '0' then
6632 if (UnalignedSupport () || BitIsClear (address, 0))
6633 {
6634 // R[t] = ZeroExtend(data, 32);
6635 context.type = eContextRegisterLoad;
6636 context.SetRegisterPlusOffset (base_reg, address - Rn);
6637 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6638 return false;
6639 }
6640 else // Can only apply before ARMv7
6641 {
6642 // R[t] = bits(32) UNKNOWN;
6643 WriteBits32Unknown (t);
6644 }
6645 }
6646 return true;
6647 }
6648
6649 // LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6650 // zero-extends it to form a 32-bit word, and writes it to a register.
6651 bool
EmulateLDRHLiteral(const uint32_t opcode,const ARMEncoding encoding)6652 EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
6653 {
6654 #if 0
6655 if ConditionPassed() then
6656 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6657 base = Align(PC,4);
6658 address = if add then (base + imm32) else (base - imm32);
6659 data = MemU[address,2];
6660 if UnalignedSupport() || address<0> = '0' then
6661 R[t] = ZeroExtend(data, 32);
6662 else // Can only apply before ARMv7
6663 R[t] = bits(32) UNKNOWN;
6664 #endif
6665
6666 bool success = false;
6667
6668 if (ConditionPassed(opcode))
6669 {
6670 uint32_t t;
6671 uint32_t imm32;
6672 bool add;
6673
6674 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6675 switch (encoding)
6676 {
6677 case eEncodingT1:
6678 // if Rt == '1111' then SEE "Unallocated memory hints";
6679 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6680 t = Bits32 (opcode, 15, 12);
6681 imm32 = Bits32 (opcode, 11, 0);
6682 add = BitIsSet (opcode, 23);
6683
6684 // if t == 13 then UNPREDICTABLE;
6685 if (t == 13)
6686 return false;
6687
6688 break;
6689
6690 case eEncodingA1:
6691 {
6692 uint32_t imm4H = Bits32 (opcode, 11, 8);
6693 uint32_t imm4L = Bits32 (opcode, 3, 0);
6694
6695 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
6696 t = Bits32 (opcode, 15, 12);
6697 imm32 = (imm4H << 4) | imm4L;
6698 add = BitIsSet (opcode, 23);
6699
6700 // if t == 15 then UNPREDICTABLE;
6701 if (t == 15)
6702 return false;
6703 break;
6704 }
6705
6706 default:
6707 return false;
6708 }
6709
6710 // base = Align(PC,4);
6711 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
6712 if (!success)
6713 return false;
6714
6715 addr_t base = AlignPC (pc_value);
6716 addr_t address;
6717
6718 // address = if add then (base + imm32) else (base - imm32);
6719 if (add)
6720 address = base + imm32;
6721 else
6722 address = base - imm32;
6723
6724 // data = MemU[address,2];
6725 RegisterInfo base_reg;
6726 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
6727
6728 EmulateInstruction::Context context;
6729 context.type = eContextRegisterLoad;
6730 context.SetRegisterPlusOffset (base_reg, address - base);
6731
6732 uint64_t data = MemURead (context, address, 2, 0, &success);
6733 if (!success)
6734 return false;
6735
6736
6737 // if UnalignedSupport() || address<0> = '0' then
6738 if (UnalignedSupport () || BitIsClear (address, 0))
6739 {
6740 // R[t] = ZeroExtend(data, 32);
6741 context.type = eContextRegisterLoad;
6742 context.SetRegisterPlusOffset (base_reg, address - base);
6743 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6744 return false;
6745
6746 }
6747 else // Can only apply before ARMv7
6748 {
6749 // R[t] = bits(32) UNKNOWN;
6750 WriteBits32Unknown (t);
6751 }
6752 }
6753 return true;
6754 }
6755
6756 // LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6757 // from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6758 // be shifted left by 0, 1, 2, or 3 bits.
6759 bool
EmulateLDRHRegister(const uint32_t opcode,const ARMEncoding encoding)6760 EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
6761 {
6762 #if 0
6763 if ConditionPassed() then
6764 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6765 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6766 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6767 address = if index then offset_addr else R[n];
6768 data = MemU[address,2];
6769 if wback then R[n] = offset_addr;
6770 if UnalignedSupport() || address<0> = '0' then
6771 R[t] = ZeroExtend(data, 32);
6772 else // Can only apply before ARMv7
6773 R[t] = bits(32) UNKNOWN;
6774 #endif
6775
6776 bool success = false;
6777
6778 if (ConditionPassed(opcode))
6779 {
6780 uint32_t t;
6781 uint32_t n;
6782 uint32_t m;
6783 bool index;
6784 bool add;
6785 bool wback;
6786 ARM_ShifterType shift_t;
6787 uint32_t shift_n;
6788
6789 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6790 switch (encoding)
6791 {
6792 case eEncodingT1:
6793 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6794 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6795 t = Bits32 (opcode, 2, 0);
6796 n = Bits32 (opcode, 5, 3);
6797 m = Bits32 (opcode, 8, 6);
6798
6799 // index = TRUE; add = TRUE; wback = FALSE;
6800 index = true;
6801 add = true;
6802 wback = false;
6803
6804 // (shift_t, shift_n) = (SRType_LSL, 0);
6805 shift_t = SRType_LSL;
6806 shift_n = 0;
6807
6808 break;
6809
6810 case eEncodingT2:
6811 // if Rn == '1111' then SEE LDRH (literal);
6812 // if Rt == '1111' then SEE "Unallocated memory hints";
6813 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6814 t = Bits32 (opcode, 15, 12);
6815 n = Bits32 (opcode, 19, 16);
6816 m = Bits32 (opcode, 3, 0);
6817
6818 // index = TRUE; add = TRUE; wback = FALSE;
6819 index = true;
6820 add = true;
6821 wback = false;
6822
6823 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6824 shift_t = SRType_LSL;
6825 shift_n = Bits32 (opcode, 5, 4);
6826
6827 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6828 if ((t == 13) || BadReg (m))
6829 return false;
6830 break;
6831
6832 case eEncodingA1:
6833 // if P == '0' && W == '1' then SEE LDRHT;
6834 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6835 t = Bits32 (opcode, 15, 12);
6836 n = Bits32 (opcode, 19, 16);
6837 m = Bits32 (opcode, 3, 0);
6838
6839 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
6840 index = BitIsSet (opcode, 24);
6841 add = BitIsSet (opcode, 23);
6842 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6843
6844 // (shift_t, shift_n) = (SRType_LSL, 0);
6845 shift_t = SRType_LSL;
6846 shift_n = 0;
6847
6848 // if t == 15 || m == 15 then UNPREDICTABLE;
6849 if ((t == 15) || (m == 15))
6850 return false;
6851
6852 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6853 if (wback && ((n == 15) || (n == t)))
6854 return false;
6855
6856 break;
6857
6858 default:
6859 return false;
6860 }
6861
6862 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6863
6864 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6865 if (!success)
6866 return false;
6867
6868 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6869 if (!success)
6870 return false;
6871
6872 addr_t offset_addr;
6873 addr_t address;
6874
6875 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6876 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6877 if (!success)
6878 return false;
6879
6880 if (add)
6881 offset_addr = Rn + offset;
6882 else
6883 offset_addr = Rn - offset;
6884
6885 // address = if index then offset_addr else R[n];
6886 if (index)
6887 address = offset_addr;
6888 else
6889 address = Rn;
6890
6891 // data = MemU[address,2];
6892 RegisterInfo base_reg;
6893 RegisterInfo offset_reg;
6894 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6895 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
6896
6897 EmulateInstruction::Context context;
6898 context.type = eContextRegisterLoad;
6899 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6900 uint64_t data = MemURead (context, address, 2, 0, &success);
6901 if (!success)
6902 return false;
6903
6904 // if wback then R[n] = offset_addr;
6905 if (wback)
6906 {
6907 context.type = eContextAdjustBaseRegister;
6908 context.SetAddress (offset_addr);
6909 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6910 return false;
6911 }
6912
6913 // if UnalignedSupport() || address<0> = '0' then
6914 if (UnalignedSupport() || BitIsClear (address, 0))
6915 {
6916 // R[t] = ZeroExtend(data, 32);
6917 context.type = eContextRegisterLoad;
6918 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6919 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6920 return false;
6921 }
6922 else // Can only apply before ARMv7
6923 {
6924 // R[t] = bits(32) UNKNOWN;
6925 WriteBits32Unknown (t);
6926 }
6927 }
6928 return true;
6929 }
6930
6931 // LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6932 // memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6933 // or pre-indexed addressing.
6934 bool
EmulateLDRSBImmediate(const uint32_t opcode,const ARMEncoding encoding)6935 EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
6936 {
6937 #if 0
6938 if ConditionPassed() then
6939 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6940 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6941 address = if index then offset_addr else R[n];
6942 R[t] = SignExtend(MemU[address,1], 32);
6943 if wback then R[n] = offset_addr;
6944 #endif
6945
6946 bool success = false;
6947
6948 if (ConditionPassed(opcode))
6949 {
6950 uint32_t t;
6951 uint32_t n;
6952 uint32_t imm32;
6953 bool index;
6954 bool add;
6955 bool wback;
6956
6957 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6958 switch (encoding)
6959 {
6960 case eEncodingT1:
6961 // if Rt == '1111' then SEE PLI;
6962 // if Rn == '1111' then SEE LDRSB (literal);
6963 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6964 t = Bits32 (opcode, 15, 12);
6965 n = Bits32 (opcode, 19, 16);
6966 imm32 = Bits32 (opcode, 11, 0);
6967
6968 // index = TRUE; add = TRUE; wback = FALSE;
6969 index = true;
6970 add = true;
6971 wback = false;
6972
6973 // if t == 13 then UNPREDICTABLE;
6974 if (t == 13)
6975 return false;
6976
6977 break;
6978
6979 case eEncodingT2:
6980 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6981 // if Rn == '1111' then SEE LDRSB (literal);
6982 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6983 // if P == '0' && W == '0' then UNDEFINED;
6984 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6985 return false;
6986
6987 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6988 t = Bits32 (opcode, 15, 12);
6989 n = Bits32 (opcode, 19, 16);
6990 imm32 = Bits32 (opcode, 7, 0);
6991
6992 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6993 index = BitIsSet (opcode, 10);
6994 add = BitIsSet (opcode, 9);
6995 wback = BitIsSet (opcode, 8);
6996
6997 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6998 if (((t == 13) || ((t == 15)
6999 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
7000 || (wback && (n == t)))
7001 return false;
7002
7003 break;
7004
7005 case eEncodingA1:
7006 {
7007 // if Rn == '1111' then SEE LDRSB (literal);
7008 // if P == '0' && W == '1' then SEE LDRSBT;
7009 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7010 t = Bits32 (opcode, 15, 12);
7011 n = Bits32 (opcode, 19, 16);
7012
7013 uint32_t imm4H = Bits32 (opcode, 11, 8);
7014 uint32_t imm4L = Bits32 (opcode, 3, 0);
7015 imm32 = (imm4H << 4) | imm4L;
7016
7017 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7018 index = BitIsSet (opcode, 24);
7019 add = BitIsSet (opcode, 23);
7020 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
7021
7022 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7023 if ((t == 15) || (wback && (n == t)))
7024 return false;
7025
7026 break;
7027 }
7028
7029 default:
7030 return false;
7031 }
7032
7033 uint64_t Rn = ReadCoreReg (n, &success);
7034 if (!success)
7035 return false;
7036
7037 addr_t offset_addr;
7038 addr_t address;
7039
7040 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7041 if (add)
7042 offset_addr = Rn + imm32;
7043 else
7044 offset_addr = Rn - imm32;
7045
7046 // address = if index then offset_addr else R[n];
7047 if (index)
7048 address = offset_addr;
7049 else
7050 address = Rn;
7051
7052 // R[t] = SignExtend(MemU[address,1], 32);
7053 RegisterInfo base_reg;
7054 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7055
7056 EmulateInstruction::Context context;
7057 context.type = eContextRegisterLoad;
7058 context.SetRegisterPlusOffset (base_reg, address - Rn);
7059
7060 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7061 if (!success)
7062 return false;
7063
7064 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7065 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7066 return false;
7067
7068 // if wback then R[n] = offset_addr;
7069 if (wback)
7070 {
7071 context.type = eContextAdjustBaseRegister;
7072 context.SetAddress (offset_addr);
7073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7074 return false;
7075 }
7076 }
7077
7078 return true;
7079 }
7080
7081 // LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7082 // sign-extends it to form a 32-bit word, and writes tit to a register.
7083 bool
EmulateLDRSBLiteral(const uint32_t opcode,const ARMEncoding encoding)7084 EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
7085 {
7086 #if 0
7087 if ConditionPassed() then
7088 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7089 base = Align(PC,4);
7090 address = if add then (base + imm32) else (base - imm32);
7091 R[t] = SignExtend(MemU[address,1], 32);
7092 #endif
7093
7094 bool success = false;
7095
7096 if (ConditionPassed(opcode))
7097 {
7098 uint32_t t;
7099 uint32_t imm32;
7100 bool add;
7101
7102 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7103 switch (encoding)
7104 {
7105 case eEncodingT1:
7106 // if Rt == '1111' then SEE PLI;
7107 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7108 t = Bits32 (opcode, 15, 12);
7109 imm32 = Bits32 (opcode, 11, 0);
7110 add = BitIsSet (opcode, 23);
7111
7112 // if t == 13 then UNPREDICTABLE;
7113 if (t == 13)
7114 return false;
7115
7116 break;
7117
7118 case eEncodingA1:
7119 {
7120 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7121 t = Bits32 (opcode, 15, 12);
7122 uint32_t imm4H = Bits32 (opcode, 11, 8);
7123 uint32_t imm4L = Bits32 (opcode, 3, 0);
7124 imm32 = (imm4H << 4) | imm4L;
7125 add = BitIsSet (opcode, 23);
7126
7127 // if t == 15 then UNPREDICTABLE;
7128 if (t == 15)
7129 return false;
7130
7131 break;
7132 }
7133
7134 default:
7135 return false;
7136 }
7137
7138 // base = Align(PC,4);
7139 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
7140 if (!success)
7141 return false;
7142 uint64_t base = AlignPC (pc_value);
7143
7144 // address = if add then (base + imm32) else (base - imm32);
7145 addr_t address;
7146 if (add)
7147 address = base + imm32;
7148 else
7149 address = base - imm32;
7150
7151 // R[t] = SignExtend(MemU[address,1], 32);
7152 RegisterInfo base_reg;
7153 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7154
7155 EmulateInstruction::Context context;
7156 context.type = eContextRegisterLoad;
7157 context.SetRegisterPlusOffset (base_reg, address - base);
7158
7159 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7160 if (!success)
7161 return false;
7162
7163 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7165 return false;
7166 }
7167 return true;
7168 }
7169
7170 // LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7171 // memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7172 // shifted left by 0, 1, 2, or 3 bits.
7173 bool
EmulateLDRSBRegister(const uint32_t opcode,const ARMEncoding encoding)7174 EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
7175 {
7176 #if 0
7177 if ConditionPassed() then
7178 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7179 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7180 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7181 address = if index then offset_addr else R[n];
7182 R[t] = SignExtend(MemU[address,1], 32);
7183 if wback then R[n] = offset_addr;
7184 #endif
7185
7186 bool success = false;
7187
7188 if (ConditionPassed(opcode))
7189 {
7190 uint32_t t;
7191 uint32_t n;
7192 uint32_t m;
7193 bool index;
7194 bool add;
7195 bool wback;
7196 ARM_ShifterType shift_t;
7197 uint32_t shift_n;
7198
7199 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7200 switch (encoding)
7201 {
7202 case eEncodingT1:
7203 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7204 t = Bits32 (opcode, 2, 0);
7205 n = Bits32 (opcode, 5, 3);
7206 m = Bits32 (opcode, 8, 6);
7207
7208 // index = TRUE; add = TRUE; wback = FALSE;
7209 index = true;
7210 add = true;
7211 wback = false;
7212
7213 // (shift_t, shift_n) = (SRType_LSL, 0);
7214 shift_t = SRType_LSL;
7215 shift_n = 0;
7216
7217 break;
7218
7219 case eEncodingT2:
7220 // if Rt == '1111' then SEE PLI;
7221 // if Rn == '1111' then SEE LDRSB (literal);
7222 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7223 t = Bits32 (opcode, 15, 12);
7224 n = Bits32 (opcode, 19, 16);
7225 m = Bits32 (opcode, 3, 0);
7226
7227 // index = TRUE; add = TRUE; wback = FALSE;
7228 index = true;
7229 add = true;
7230 wback = false;
7231
7232 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7233 shift_t = SRType_LSL;
7234 shift_n = Bits32 (opcode, 5, 4);
7235
7236 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7237 if ((t == 13) || BadReg (m))
7238 return false;
7239 break;
7240
7241 case eEncodingA1:
7242 // if P == '0' && W == '1' then SEE LDRSBT;
7243 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7244 t = Bits32 (opcode, 15, 12);
7245 n = Bits32 (opcode, 19, 16);
7246 m = Bits32 (opcode, 3, 0);
7247
7248 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7249 index = BitIsSet (opcode, 24);
7250 add = BitIsSet (opcode, 23);
7251 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7252
7253 // (shift_t, shift_n) = (SRType_LSL, 0);
7254 shift_t = SRType_LSL;
7255 shift_n = 0;
7256
7257 // if t == 15 || m == 15 then UNPREDICTABLE;
7258 if ((t == 15) || (m == 15))
7259 return false;
7260
7261 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7262 if (wback && ((n == 15) || (n == t)))
7263 return false;
7264 break;
7265
7266 default:
7267 return false;
7268 }
7269
7270 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7271 if (!success)
7272 return false;
7273
7274 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7275 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7276 if (!success)
7277 return false;
7278
7279 addr_t offset_addr;
7280 addr_t address;
7281
7282 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7283 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7284 if (!success)
7285 return false;
7286
7287 if (add)
7288 offset_addr = Rn + offset;
7289 else
7290 offset_addr = Rn - offset;
7291
7292 // address = if index then offset_addr else R[n];
7293 if (index)
7294 address = offset_addr;
7295 else
7296 address = Rn;
7297
7298 // R[t] = SignExtend(MemU[address,1], 32);
7299 RegisterInfo base_reg;
7300 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7301 RegisterInfo offset_reg;
7302 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7303
7304 EmulateInstruction::Context context;
7305 context.type = eContextRegisterLoad;
7306 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7307
7308 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7309 if (!success)
7310 return false;
7311
7312 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7313 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7314 return false;
7315
7316 // if wback then R[n] = offset_addr;
7317 if (wback)
7318 {
7319 context.type = eContextAdjustBaseRegister;
7320 context.SetAddress (offset_addr);
7321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7322 return false;
7323 }
7324 }
7325 return true;
7326 }
7327
7328 // LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7329 // memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7330 // pre-indexed addressing.
7331 bool
EmulateLDRSHImmediate(const uint32_t opcode,const ARMEncoding encoding)7332 EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
7333 {
7334 #if 0
7335 if ConditionPassed() then
7336 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7337 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7338 address = if index then offset_addr else R[n];
7339 data = MemU[address,2];
7340 if wback then R[n] = offset_addr;
7341 if UnalignedSupport() || address<0> = '0' then
7342 R[t] = SignExtend(data, 32);
7343 else // Can only apply before ARMv7
7344 R[t] = bits(32) UNKNOWN;
7345 #endif
7346
7347 bool success = false;
7348
7349 if (ConditionPassed(opcode))
7350 {
7351 uint32_t t;
7352 uint32_t n;
7353 uint32_t imm32;
7354 bool index;
7355 bool add;
7356 bool wback;
7357
7358 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7359 switch (encoding)
7360 {
7361 case eEncodingT1:
7362 // if Rn == '1111' then SEE LDRSH (literal);
7363 // if Rt == '1111' then SEE "Unallocated memory hints";
7364 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7365 t = Bits32 (opcode, 15, 12);
7366 n = Bits32 (opcode, 19, 16);
7367 imm32 = Bits32 (opcode, 11, 0);
7368
7369 // index = TRUE; add = TRUE; wback = FALSE;
7370 index = true;
7371 add = true;
7372 wback = false;
7373
7374 // if t == 13 then UNPREDICTABLE;
7375 if (t == 13)
7376 return false;
7377
7378 break;
7379
7380 case eEncodingT2:
7381 // if Rn == '1111' then SEE LDRSH (literal);
7382 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7383 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7384 // if P == '0' && W == '0' then UNDEFINED;
7385 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7386 return false;
7387
7388 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7389 t = Bits32 (opcode, 15, 12);
7390 n = Bits32 (opcode, 19, 16);
7391 imm32 = Bits32 (opcode, 7, 0);
7392
7393 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7394 index = BitIsSet (opcode, 10);
7395 add = BitIsSet (opcode, 9);
7396 wback = BitIsSet (opcode, 8);
7397
7398 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7399 if (BadReg (t) || (wback && (n == t)))
7400 return false;
7401
7402 break;
7403
7404 case eEncodingA1:
7405 {
7406 // if Rn == '1111' then SEE LDRSH (literal);
7407 // if P == '0' && W == '1' then SEE LDRSHT;
7408 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7409 t = Bits32 (opcode, 15, 12);
7410 n = Bits32 (opcode, 19, 16);
7411 uint32_t imm4H = Bits32 (opcode, 11,8);
7412 uint32_t imm4L = Bits32 (opcode, 3, 0);
7413 imm32 = (imm4H << 4) | imm4L;
7414
7415 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7416 index = BitIsSet (opcode, 24);
7417 add = BitIsSet (opcode, 23);
7418 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7419
7420 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7421 if ((t == 15) || (wback && (n == t)))
7422 return false;
7423
7424 break;
7425 }
7426
7427 default:
7428 return false;
7429 }
7430
7431 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7432 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7433 if (!success)
7434 return false;
7435
7436 addr_t offset_addr;
7437 if (add)
7438 offset_addr = Rn + imm32;
7439 else
7440 offset_addr = Rn - imm32;
7441
7442 // address = if index then offset_addr else R[n];
7443 addr_t address;
7444 if (index)
7445 address = offset_addr;
7446 else
7447 address = Rn;
7448
7449 // data = MemU[address,2];
7450 RegisterInfo base_reg;
7451 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7452
7453 EmulateInstruction::Context context;
7454 context.type = eContextRegisterLoad;
7455 context.SetRegisterPlusOffset (base_reg, address - Rn);
7456
7457 uint64_t data = MemURead (context, address, 2, 0, &success);
7458 if (!success)
7459 return false;
7460
7461 // if wback then R[n] = offset_addr;
7462 if (wback)
7463 {
7464 context.type = eContextAdjustBaseRegister;
7465 context.SetAddress (offset_addr);
7466 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7467 return false;
7468 }
7469
7470 // if UnalignedSupport() || address<0> = '0' then
7471 if (UnalignedSupport() || BitIsClear (address, 0))
7472 {
7473 // R[t] = SignExtend(data, 32);
7474 int64_t signed_data = llvm::SignExtend64<16>(data);
7475 context.type = eContextRegisterLoad;
7476 context.SetRegisterPlusOffset (base_reg, address - Rn);
7477 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7478 return false;
7479 }
7480 else // Can only apply before ARMv7
7481 {
7482 // R[t] = bits(32) UNKNOWN;
7483 WriteBits32Unknown (t);
7484 }
7485 }
7486 return true;
7487 }
7488
7489 // LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7490 // sign-extends it to from a 32-bit word, and writes it to a register.
7491 bool
EmulateLDRSHLiteral(const uint32_t opcode,const ARMEncoding encoding)7492 EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
7493 {
7494 #if 0
7495 if ConditionPassed() then
7496 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7497 base = Align(PC,4);
7498 address = if add then (base + imm32) else (base - imm32);
7499 data = MemU[address,2];
7500 if UnalignedSupport() || address<0> = '0' then
7501 R[t] = SignExtend(data, 32);
7502 else // Can only apply before ARMv7
7503 R[t] = bits(32) UNKNOWN;
7504 #endif
7505
7506 bool success = false;
7507
7508 if (ConditionPassed(opcode))
7509 {
7510 uint32_t t;
7511 uint32_t imm32;
7512 bool add;
7513
7514 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7515 switch (encoding)
7516 {
7517 case eEncodingT1:
7518 // if Rt == '1111' then SEE "Unallocated memory hints";
7519 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7520 t = Bits32 (opcode, 15, 12);
7521 imm32 = Bits32 (opcode, 11, 0);
7522 add = BitIsSet (opcode, 23);
7523
7524 // if t == 13 then UNPREDICTABLE;
7525 if (t == 13)
7526 return false;
7527
7528 break;
7529
7530 case eEncodingA1:
7531 {
7532 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7533 t = Bits32 (opcode, 15, 12);
7534 uint32_t imm4H = Bits32 (opcode, 11, 8);
7535 uint32_t imm4L = Bits32 (opcode, 3, 0);
7536 imm32 = (imm4H << 4) | imm4L;
7537 add = BitIsSet (opcode, 23);
7538
7539 // if t == 15 then UNPREDICTABLE;
7540 if (t == 15)
7541 return false;
7542
7543 break;
7544 }
7545 default:
7546 return false;
7547 }
7548
7549 // base = Align(PC,4);
7550 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
7551 if (!success)
7552 return false;
7553
7554 uint64_t base = AlignPC (pc_value);
7555
7556 addr_t address;
7557 // address = if add then (base + imm32) else (base - imm32);
7558 if (add)
7559 address = base + imm32;
7560 else
7561 address = base - imm32;
7562
7563 // data = MemU[address,2];
7564 RegisterInfo base_reg;
7565 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
7566
7567 EmulateInstruction::Context context;
7568 context.type = eContextRegisterLoad;
7569 context.SetRegisterPlusOffset (base_reg, imm32);
7570
7571 uint64_t data = MemURead (context, address, 2, 0, &success);
7572 if (!success)
7573 return false;
7574
7575 // if UnalignedSupport() || address<0> = '0' then
7576 if (UnalignedSupport() || BitIsClear (address, 0))
7577 {
7578 // R[t] = SignExtend(data, 32);
7579 int64_t signed_data = llvm::SignExtend64<16>(data);
7580 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7581 return false;
7582 }
7583 else // Can only apply before ARMv7
7584 {
7585 // R[t] = bits(32) UNKNOWN;
7586 WriteBits32Unknown (t);
7587 }
7588 }
7589 return true;
7590 }
7591
7592 // LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7593 // from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7594 // shifted left by 0, 1, 2, or 3 bits.
7595 bool
EmulateLDRSHRegister(const uint32_t opcode,const ARMEncoding encoding)7596 EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
7597 {
7598 #if 0
7599 if ConditionPassed() then
7600 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7601 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7602 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7603 address = if index then offset_addr else R[n];
7604 data = MemU[address,2];
7605 if wback then R[n] = offset_addr;
7606 if UnalignedSupport() || address<0> = '0' then
7607 R[t] = SignExtend(data, 32);
7608 else // Can only apply before ARMv7
7609 R[t] = bits(32) UNKNOWN;
7610 #endif
7611
7612 bool success = false;
7613
7614 if (ConditionPassed(opcode))
7615 {
7616 uint32_t t;
7617 uint32_t n;
7618 uint32_t m;
7619 bool index;
7620 bool add;
7621 bool wback;
7622 ARM_ShifterType shift_t;
7623 uint32_t shift_n;
7624
7625 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7626 switch (encoding)
7627 {
7628 case eEncodingT1:
7629 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7630 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7631 t = Bits32 (opcode, 2, 0);
7632 n = Bits32 (opcode, 5, 3);
7633 m = Bits32 (opcode, 8, 6);
7634
7635 // index = TRUE; add = TRUE; wback = FALSE;
7636 index = true;
7637 add = true;
7638 wback = false;
7639
7640 // (shift_t, shift_n) = (SRType_LSL, 0);
7641 shift_t = SRType_LSL;
7642 shift_n = 0;
7643
7644 break;
7645
7646 case eEncodingT2:
7647 // if Rn == '1111' then SEE LDRSH (literal);
7648 // if Rt == '1111' then SEE "Unallocated memory hints";
7649 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7650 t = Bits32 (opcode, 15, 12);
7651 n = Bits32 (opcode, 19, 16);
7652 m = Bits32 (opcode, 3, 0);
7653
7654 // index = TRUE; add = TRUE; wback = FALSE;
7655 index = true;
7656 add = true;
7657 wback = false;
7658
7659 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7660 shift_t = SRType_LSL;
7661 shift_n = Bits32 (opcode, 5, 4);
7662
7663 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7664 if ((t == 13) || BadReg (m))
7665 return false;
7666
7667 break;
7668
7669 case eEncodingA1:
7670 // if P == '0' && W == '1' then SEE LDRSHT;
7671 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7672 t = Bits32 (opcode, 15, 12);
7673 n = Bits32 (opcode, 19, 16);
7674 m = Bits32 (opcode, 3, 0);
7675
7676 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
7677 index = BitIsSet (opcode, 24);
7678 add = BitIsSet (opcode, 23);
7679 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7680
7681 // (shift_t, shift_n) = (SRType_LSL, 0);
7682 shift_t = SRType_LSL;
7683 shift_n = 0;
7684
7685 // if t == 15 || m == 15 then UNPREDICTABLE;
7686 if ((t == 15) || (m == 15))
7687 return false;
7688
7689 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7690 if (wback && ((n == 15) || (n == t)))
7691 return false;
7692
7693 break;
7694
7695 default:
7696 return false;
7697 }
7698
7699 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7700 if (!success)
7701 return false;
7702
7703 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7704 if (!success)
7705 return false;
7706
7707 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7708 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7709 if (!success)
7710 return false;
7711
7712 addr_t offset_addr;
7713 addr_t address;
7714
7715 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7716 if (add)
7717 offset_addr = Rn + offset;
7718 else
7719 offset_addr = Rn - offset;
7720
7721 // address = if index then offset_addr else R[n];
7722 if (index)
7723 address = offset_addr;
7724 else
7725 address = Rn;
7726
7727 // data = MemU[address,2];
7728 RegisterInfo base_reg;
7729 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7730
7731 RegisterInfo offset_reg;
7732 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
7733
7734 EmulateInstruction::Context context;
7735 context.type = eContextRegisterLoad;
7736 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7737
7738 uint64_t data = MemURead (context, address, 2, 0, &success);
7739 if (!success)
7740 return false;
7741
7742 // if wback then R[n] = offset_addr;
7743 if (wback)
7744 {
7745 context.type = eContextAdjustBaseRegister;
7746 context.SetAddress (offset_addr);
7747 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7748 return false;
7749 }
7750
7751 // if UnalignedSupport() || address<0> = '0' then
7752 if (UnalignedSupport() || BitIsClear (address, 0))
7753 {
7754 // R[t] = SignExtend(data, 32);
7755 context.type = eContextRegisterLoad;
7756 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7757
7758 int64_t signed_data = llvm::SignExtend64<16>(data);
7759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7760 return false;
7761 }
7762 else // Can only apply before ARMv7
7763 {
7764 // R[t] = bits(32) UNKNOWN;
7765 WriteBits32Unknown (t);
7766 }
7767 }
7768 return true;
7769 }
7770
7771 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7772 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7773 bool
EmulateSXTB(const uint32_t opcode,const ARMEncoding encoding)7774 EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
7775 {
7776 #if 0
7777 if ConditionPassed() then
7778 EncodingSpecificOperations();
7779 rotated = ROR(R[m], rotation);
7780 R[d] = SignExtend(rotated<7:0>, 32);
7781 #endif
7782
7783 bool success = false;
7784
7785 if (ConditionPassed(opcode))
7786 {
7787 uint32_t d;
7788 uint32_t m;
7789 uint32_t rotation;
7790
7791 // EncodingSpecificOperations();
7792 switch (encoding)
7793 {
7794 case eEncodingT1:
7795 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7796 d = Bits32 (opcode, 2, 0);
7797 m = Bits32 (opcode, 5, 3);
7798 rotation = 0;
7799
7800 break;
7801
7802 case eEncodingT2:
7803 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7804 d = Bits32 (opcode, 11, 8);
7805 m = Bits32 (opcode, 3, 0);
7806 rotation = Bits32 (opcode, 5, 4) << 3;
7807
7808 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7809 if (BadReg (d) || BadReg (m))
7810 return false;
7811
7812 break;
7813
7814 case eEncodingA1:
7815 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7816 d = Bits32 (opcode, 15, 12);
7817 m = Bits32 (opcode, 3, 0);
7818 rotation = Bits32 (opcode, 11, 10) << 3;
7819
7820 // if d == 15 || m == 15 then UNPREDICTABLE;
7821 if ((d == 15) || (m == 15))
7822 return false;
7823
7824 break;
7825
7826 default:
7827 return false;
7828 }
7829
7830 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7831 if (!success)
7832 return false;
7833
7834 // rotated = ROR(R[m], rotation);
7835 uint64_t rotated = ROR (Rm, rotation, &success);
7836 if (!success)
7837 return false;
7838
7839 // R[d] = SignExtend(rotated<7:0>, 32);
7840 int64_t data = llvm::SignExtend64<8>(rotated);
7841
7842 RegisterInfo source_reg;
7843 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
7844
7845 EmulateInstruction::Context context;
7846 context.type = eContextRegisterLoad;
7847 context.SetRegister (source_reg);
7848
7849 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
7850 return false;
7851 }
7852 return true;
7853 }
7854
7855 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7856 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7857 bool
EmulateSXTH(const uint32_t opcode,const ARMEncoding encoding)7858 EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
7859 {
7860 #if 0
7861 if ConditionPassed() then
7862 EncodingSpecificOperations();
7863 rotated = ROR(R[m], rotation);
7864 R[d] = SignExtend(rotated<15:0>, 32);
7865 #endif
7866
7867 bool success = false;
7868
7869 if (ConditionPassed(opcode))
7870 {
7871 uint32_t d;
7872 uint32_t m;
7873 uint32_t rotation;
7874
7875 // EncodingSpecificOperations();
7876 switch (encoding)
7877 {
7878 case eEncodingT1:
7879 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7880 d = Bits32 (opcode, 2, 0);
7881 m = Bits32 (opcode, 5, 3);
7882 rotation = 0;
7883
7884 break;
7885
7886 case eEncodingT2:
7887 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7888 d = Bits32 (opcode, 11, 8);
7889 m = Bits32 (opcode, 3, 0);
7890 rotation = Bits32 (opcode, 5, 4) << 3;
7891
7892 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7893 if (BadReg (d) || BadReg (m))
7894 return false;
7895
7896 break;
7897
7898 case eEncodingA1:
7899 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7900 d = Bits32 (opcode, 15, 12);
7901 m = Bits32 (opcode, 3, 0);
7902 rotation = Bits32 (opcode, 11, 10) << 3;
7903
7904 // if d == 15 || m == 15 then UNPREDICTABLE;
7905 if ((d == 15) || (m == 15))
7906 return false;
7907
7908 break;
7909
7910 default:
7911 return false;
7912 }
7913
7914 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7915 if (!success)
7916 return false;
7917
7918 // rotated = ROR(R[m], rotation);
7919 uint64_t rotated = ROR (Rm, rotation, &success);
7920 if (!success)
7921 return false;
7922
7923 // R[d] = SignExtend(rotated<15:0>, 32);
7924 RegisterInfo source_reg;
7925 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
7926
7927 EmulateInstruction::Context context;
7928 context.type = eContextRegisterLoad;
7929 context.SetRegister (source_reg);
7930
7931 int64_t data = llvm::SignExtend64<16> (rotated);
7932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
7933 return false;
7934 }
7935
7936 return true;
7937 }
7938
7939 // UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7940 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7941 bool
EmulateUXTB(const uint32_t opcode,const ARMEncoding encoding)7942 EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
7943 {
7944 #if 0
7945 if ConditionPassed() then
7946 EncodingSpecificOperations();
7947 rotated = ROR(R[m], rotation);
7948 R[d] = ZeroExtend(rotated<7:0>, 32);
7949 #endif
7950
7951 bool success = false;
7952
7953 if (ConditionPassed(opcode))
7954 {
7955 uint32_t d;
7956 uint32_t m;
7957 uint32_t rotation;
7958
7959 // EncodingSpecificOperations();
7960 switch (encoding)
7961 {
7962 case eEncodingT1:
7963 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7964 d = Bits32 (opcode, 2, 0);
7965 m = Bits32 (opcode, 5, 3);
7966 rotation = 0;
7967
7968 break;
7969
7970 case eEncodingT2:
7971 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7972 d = Bits32 (opcode, 11, 8);
7973 m = Bits32 (opcode, 3, 0);
7974 rotation = Bits32 (opcode, 5, 4) << 3;
7975
7976 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7977 if (BadReg (d) || BadReg (m))
7978 return false;
7979
7980 break;
7981
7982 case eEncodingA1:
7983 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7984 d = Bits32 (opcode, 15, 12);
7985 m = Bits32 (opcode, 3, 0);
7986 rotation = Bits32 (opcode, 11, 10) << 3;
7987
7988 // if d == 15 || m == 15 then UNPREDICTABLE;
7989 if ((d == 15) || (m == 15))
7990 return false;
7991
7992 break;
7993
7994 default:
7995 return false;
7996 }
7997
7998 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7999 if (!success)
8000 return false;
8001
8002 // rotated = ROR(R[m], rotation);
8003 uint64_t rotated = ROR (Rm, rotation, &success);
8004 if (!success)
8005 return false;
8006
8007 // R[d] = ZeroExtend(rotated<7:0>, 32);
8008 RegisterInfo source_reg;
8009 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8010
8011 EmulateInstruction::Context context;
8012 context.type = eContextRegisterLoad;
8013 context.SetRegister (source_reg);
8014
8015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
8016 return false;
8017 }
8018 return true;
8019 }
8020
8021 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
8022 // register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
8023 bool
EmulateUXTH(const uint32_t opcode,const ARMEncoding encoding)8024 EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
8025 {
8026 #if 0
8027 if ConditionPassed() then
8028 EncodingSpecificOperations();
8029 rotated = ROR(R[m], rotation);
8030 R[d] = ZeroExtend(rotated<15:0>, 32);
8031 #endif
8032
8033 bool success = false;
8034
8035 if (ConditionPassed(opcode))
8036 {
8037 uint32_t d;
8038 uint32_t m;
8039 uint32_t rotation;
8040
8041 switch (encoding)
8042 {
8043 case eEncodingT1:
8044 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8045 d = Bits32 (opcode, 2, 0);
8046 m = Bits32 (opcode, 5, 3);
8047 rotation = 0;
8048
8049 break;
8050
8051 case eEncodingT2:
8052 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8053 d = Bits32 (opcode, 11, 8);
8054 m = Bits32 (opcode, 3, 0);
8055 rotation = Bits32 (opcode, 5, 4) << 3;
8056
8057 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8058 if (BadReg (d) || BadReg (m))
8059 return false;
8060
8061 break;
8062
8063 case eEncodingA1:
8064 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8065 d = Bits32 (opcode, 15, 12);
8066 m = Bits32 (opcode, 3, 0);
8067 rotation = Bits32 (opcode, 11, 10) << 3;
8068
8069 // if d == 15 || m == 15 then UNPREDICTABLE;
8070 if ((d == 15) || (m == 15))
8071 return false;
8072
8073 break;
8074
8075 default:
8076 return false;
8077 }
8078
8079 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8080 if (!success)
8081 return false;
8082
8083 // rotated = ROR(R[m], rotation);
8084 uint64_t rotated = ROR (Rm, rotation, &success);
8085 if (!success)
8086 return false;
8087
8088 // R[d] = ZeroExtend(rotated<15:0>, 32);
8089 RegisterInfo source_reg;
8090 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
8091
8092 EmulateInstruction::Context context;
8093 context.type = eContextRegisterLoad;
8094 context.SetRegister (source_reg);
8095
8096 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8097 return false;
8098 }
8099 return true;
8100 }
8101
8102 // RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8103 // word respectively.
8104 bool
EmulateRFE(const uint32_t opcode,const ARMEncoding encoding)8105 EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
8106 {
8107 #if 0
8108 if ConditionPassed() then
8109 EncodingSpecificOperations();
8110 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8111 UNPREDICTABLE;
8112 else
8113 address = if increment then R[n] else R[n]-8;
8114 if wordhigher then address = address+4;
8115 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8116 BranchWritePC(MemA[address,4]);
8117 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8118 #endif
8119
8120 bool success = false;
8121
8122 if (ConditionPassed(opcode))
8123 {
8124 uint32_t n;
8125 bool wback;
8126 bool increment;
8127 bool wordhigher;
8128
8129 // EncodingSpecificOperations();
8130 switch (encoding)
8131 {
8132 case eEncodingT1:
8133 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
8134 n = Bits32 (opcode, 19, 16);
8135 wback = BitIsSet (opcode, 21);
8136 increment = false;
8137 wordhigher = false;
8138
8139 // if n == 15 then UNPREDICTABLE;
8140 if (n == 15)
8141 return false;
8142
8143 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8144 if (InITBlock() && !LastInITBlock())
8145 return false;
8146
8147 break;
8148
8149 case eEncodingT2:
8150 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8151 n = Bits32 (opcode, 19, 16);
8152 wback = BitIsSet (opcode, 21);
8153 increment = true;
8154 wordhigher = false;
8155
8156 // if n == 15 then UNPREDICTABLE;
8157 if (n == 15)
8158 return false;
8159
8160 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8161 if (InITBlock() && !LastInITBlock())
8162 return false;
8163
8164 break;
8165
8166 case eEncodingA1:
8167 // n = UInt(Rn);
8168 n = Bits32 (opcode, 19, 16);
8169
8170 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8171 wback = BitIsSet (opcode, 21);
8172 increment = BitIsSet (opcode, 23);
8173 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8174
8175 // if n == 15 then UNPREDICTABLE;
8176 if (n == 15)
8177 return false;
8178
8179 break;
8180
8181 default:
8182 return false;
8183 }
8184
8185 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8186 if (!CurrentModeIsPrivileged ())
8187 // UNPREDICTABLE;
8188 return false;
8189 else
8190 {
8191 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8192 if (!success)
8193 return false;
8194
8195 addr_t address;
8196 // address = if increment then R[n] else R[n]-8;
8197 if (increment)
8198 address = Rn;
8199 else
8200 address = Rn - 8;
8201
8202 // if wordhigher then address = address+4;
8203 if (wordhigher)
8204 address = address + 4;
8205
8206 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8207 RegisterInfo base_reg;
8208 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
8209
8210 EmulateInstruction::Context context;
8211 context.type = eContextReturnFromException;
8212 context.SetRegisterPlusOffset (base_reg, address - Rn);
8213
8214 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8215 if (!success)
8216 return false;
8217
8218 CPSRWriteByInstr (data, 15, true);
8219
8220 // BranchWritePC(MemA[address,4]);
8221 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8222 if (!success)
8223 return false;
8224
8225 BranchWritePC (context, data2);
8226
8227 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8228 if (wback)
8229 {
8230 context.type = eContextAdjustBaseRegister;
8231 if (increment)
8232 {
8233 context.SetOffset (8);
8234 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8235 return false;
8236 }
8237 else
8238 {
8239 context.SetOffset (-8);
8240 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8241 return false;
8242 }
8243 } // if wback
8244 }
8245 } // if ConditionPassed()
8246 return true;
8247 }
8248
8249 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8250 // and writes the result to the destination register. It can optionally update the condition flags based on
8251 // the result.
8252 bool
EmulateEORImm(const uint32_t opcode,const ARMEncoding encoding)8253 EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
8254 {
8255 #if 0
8256 // ARM pseudo code...
8257 if ConditionPassed() then
8258 EncodingSpecificOperations();
8259 result = R[n] EOR imm32;
8260 if d == 15 then // Can only occur for ARM encoding
8261 ALUWritePC(result); // setflags is always FALSE here
8262 else
8263 R[d] = result;
8264 if setflags then
8265 APSR.N = result<31>;
8266 APSR.Z = IsZeroBit(result);
8267 APSR.C = carry;
8268 // APSR.V unchanged
8269 #endif
8270
8271 bool success = false;
8272
8273 if (ConditionPassed(opcode))
8274 {
8275 uint32_t Rd, Rn;
8276 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8277 bool setflags;
8278 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8279 switch (encoding)
8280 {
8281 case eEncodingT1:
8282 Rd = Bits32(opcode, 11, 8);
8283 Rn = Bits32(opcode, 19, 16);
8284 setflags = BitIsSet(opcode, 20);
8285 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8286 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8287 if (Rd == 15 && setflags)
8288 return EmulateTEQImm (opcode, eEncodingT1);
8289 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8290 return false;
8291 break;
8292 case eEncodingA1:
8293 Rd = Bits32(opcode, 15, 12);
8294 Rn = Bits32(opcode, 19, 16);
8295 setflags = BitIsSet(opcode, 20);
8296 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8297
8298 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8299 if (Rd == 15 && setflags)
8300 return EmulateSUBSPcLrEtc (opcode, encoding);
8301 break;
8302 default:
8303 return false;
8304 }
8305
8306 // Read the first operand.
8307 uint32_t val1 = ReadCoreReg(Rn, &success);
8308 if (!success)
8309 return false;
8310
8311 uint32_t result = val1 ^ imm32;
8312
8313 EmulateInstruction::Context context;
8314 context.type = EmulateInstruction::eContextImmediate;
8315 context.SetNoArgs ();
8316
8317 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8318 return false;
8319 }
8320 return true;
8321 }
8322
8323 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8324 // optionally-shifted register value, and writes the result to the destination register.
8325 // It can optionally update the condition flags based on the result.
8326 bool
EmulateEORReg(const uint32_t opcode,const ARMEncoding encoding)8327 EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
8328 {
8329 #if 0
8330 // ARM pseudo code...
8331 if ConditionPassed() then
8332 EncodingSpecificOperations();
8333 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8334 result = R[n] EOR shifted;
8335 if d == 15 then // Can only occur for ARM encoding
8336 ALUWritePC(result); // setflags is always FALSE here
8337 else
8338 R[d] = result;
8339 if setflags then
8340 APSR.N = result<31>;
8341 APSR.Z = IsZeroBit(result);
8342 APSR.C = carry;
8343 // APSR.V unchanged
8344 #endif
8345
8346 bool success = false;
8347
8348 if (ConditionPassed(opcode))
8349 {
8350 uint32_t Rd, Rn, Rm;
8351 ARM_ShifterType shift_t;
8352 uint32_t shift_n; // the shift applied to the value read from Rm
8353 bool setflags;
8354 uint32_t carry;
8355 switch (encoding)
8356 {
8357 case eEncodingT1:
8358 Rd = Rn = Bits32(opcode, 2, 0);
8359 Rm = Bits32(opcode, 5, 3);
8360 setflags = !InITBlock();
8361 shift_t = SRType_LSL;
8362 shift_n = 0;
8363 break;
8364 case eEncodingT2:
8365 Rd = Bits32(opcode, 11, 8);
8366 Rn = Bits32(opcode, 19, 16);
8367 Rm = Bits32(opcode, 3, 0);
8368 setflags = BitIsSet(opcode, 20);
8369 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8370 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8371 if (Rd == 15 && setflags)
8372 return EmulateTEQReg (opcode, eEncodingT1);
8373 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8374 return false;
8375 break;
8376 case eEncodingA1:
8377 Rd = Bits32(opcode, 15, 12);
8378 Rn = Bits32(opcode, 19, 16);
8379 Rm = Bits32(opcode, 3, 0);
8380 setflags = BitIsSet(opcode, 20);
8381 shift_n = DecodeImmShiftARM(opcode, shift_t);
8382
8383 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8384 if (Rd == 15 && setflags)
8385 return EmulateSUBSPcLrEtc (opcode, encoding);
8386 break;
8387 default:
8388 return false;
8389 }
8390
8391 // Read the first operand.
8392 uint32_t val1 = ReadCoreReg(Rn, &success);
8393 if (!success)
8394 return false;
8395
8396 // Read the second operand.
8397 uint32_t val2 = ReadCoreReg(Rm, &success);
8398 if (!success)
8399 return false;
8400
8401 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8402 if (!success)
8403 return false;
8404 uint32_t result = val1 ^ shifted;
8405
8406 EmulateInstruction::Context context;
8407 context.type = EmulateInstruction::eContextImmediate;
8408 context.SetNoArgs ();
8409
8410 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8411 return false;
8412 }
8413 return true;
8414 }
8415
8416 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8417 // writes the result to the destination register. It can optionally update the condition flags based
8418 // on the result.
8419 bool
EmulateORRImm(const uint32_t opcode,const ARMEncoding encoding)8420 EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
8421 {
8422 #if 0
8423 // ARM pseudo code...
8424 if ConditionPassed() then
8425 EncodingSpecificOperations();
8426 result = R[n] OR imm32;
8427 if d == 15 then // Can only occur for ARM encoding
8428 ALUWritePC(result); // setflags is always FALSE here
8429 else
8430 R[d] = result;
8431 if setflags then
8432 APSR.N = result<31>;
8433 APSR.Z = IsZeroBit(result);
8434 APSR.C = carry;
8435 // APSR.V unchanged
8436 #endif
8437
8438 bool success = false;
8439
8440 if (ConditionPassed(opcode))
8441 {
8442 uint32_t Rd, Rn;
8443 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8444 bool setflags;
8445 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8446 switch (encoding)
8447 {
8448 case eEncodingT1:
8449 Rd = Bits32(opcode, 11, 8);
8450 Rn = Bits32(opcode, 19, 16);
8451 setflags = BitIsSet(opcode, 20);
8452 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8453 // if Rn == '1111' then SEE MOV (immediate);
8454 if (Rn == 15)
8455 return EmulateMOVRdImm (opcode, eEncodingT2);
8456 if (BadReg(Rd) || Rn == 13)
8457 return false;
8458 break;
8459 case eEncodingA1:
8460 Rd = Bits32(opcode, 15, 12);
8461 Rn = Bits32(opcode, 19, 16);
8462 setflags = BitIsSet(opcode, 20);
8463 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8464
8465 if (Rd == 15 && setflags)
8466 return EmulateSUBSPcLrEtc (opcode, encoding);
8467 break;
8468 default:
8469 return false;
8470 }
8471
8472 // Read the first operand.
8473 uint32_t val1 = ReadCoreReg(Rn, &success);
8474 if (!success)
8475 return false;
8476
8477 uint32_t result = val1 | imm32;
8478
8479 EmulateInstruction::Context context;
8480 context.type = EmulateInstruction::eContextImmediate;
8481 context.SetNoArgs ();
8482
8483 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8484 return false;
8485 }
8486 return true;
8487 }
8488
8489 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8490 // value, and writes the result to the destination register. It can optionally update the condition flags based
8491 // on the result.
8492 bool
EmulateORRReg(const uint32_t opcode,const ARMEncoding encoding)8493 EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
8494 {
8495 #if 0
8496 // ARM pseudo code...
8497 if ConditionPassed() then
8498 EncodingSpecificOperations();
8499 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8500 result = R[n] OR shifted;
8501 if d == 15 then // Can only occur for ARM encoding
8502 ALUWritePC(result); // setflags is always FALSE here
8503 else
8504 R[d] = result;
8505 if setflags then
8506 APSR.N = result<31>;
8507 APSR.Z = IsZeroBit(result);
8508 APSR.C = carry;
8509 // APSR.V unchanged
8510 #endif
8511
8512 bool success = false;
8513
8514 if (ConditionPassed(opcode))
8515 {
8516 uint32_t Rd, Rn, Rm;
8517 ARM_ShifterType shift_t;
8518 uint32_t shift_n; // the shift applied to the value read from Rm
8519 bool setflags;
8520 uint32_t carry;
8521 switch (encoding)
8522 {
8523 case eEncodingT1:
8524 Rd = Rn = Bits32(opcode, 2, 0);
8525 Rm = Bits32(opcode, 5, 3);
8526 setflags = !InITBlock();
8527 shift_t = SRType_LSL;
8528 shift_n = 0;
8529 break;
8530 case eEncodingT2:
8531 Rd = Bits32(opcode, 11, 8);
8532 Rn = Bits32(opcode, 19, 16);
8533 Rm = Bits32(opcode, 3, 0);
8534 setflags = BitIsSet(opcode, 20);
8535 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8536 // if Rn == '1111' then SEE MOV (register);
8537 if (Rn == 15)
8538 return EmulateMOVRdRm (opcode, eEncodingT3);
8539 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8540 return false;
8541 break;
8542 case eEncodingA1:
8543 Rd = Bits32(opcode, 15, 12);
8544 Rn = Bits32(opcode, 19, 16);
8545 Rm = Bits32(opcode, 3, 0);
8546 setflags = BitIsSet(opcode, 20);
8547 shift_n = DecodeImmShiftARM(opcode, shift_t);
8548
8549 if (Rd == 15 && setflags)
8550 return EmulateSUBSPcLrEtc (opcode, encoding);
8551 break;
8552 default:
8553 return false;
8554 }
8555
8556 // Read the first operand.
8557 uint32_t val1 = ReadCoreReg(Rn, &success);
8558 if (!success)
8559 return false;
8560
8561 // Read the second operand.
8562 uint32_t val2 = ReadCoreReg(Rm, &success);
8563 if (!success)
8564 return false;
8565
8566 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8567 if (!success)
8568 return false;
8569 uint32_t result = val1 | shifted;
8570
8571 EmulateInstruction::Context context;
8572 context.type = EmulateInstruction::eContextImmediate;
8573 context.SetNoArgs ();
8574
8575 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8576 return false;
8577 }
8578 return true;
8579 }
8580
8581 // Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8582 // the destination register. It can optionally update the condition flags based on the result.
8583 bool
EmulateRSBImm(const uint32_t opcode,const ARMEncoding encoding)8584 EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
8585 {
8586 #if 0
8587 // ARM pseudo code...
8588 if ConditionPassed() then
8589 EncodingSpecificOperations();
8590 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8591 if d == 15 then // Can only occur for ARM encoding
8592 ALUWritePC(result); // setflags is always FALSE here
8593 else
8594 R[d] = result;
8595 if setflags then
8596 APSR.N = result<31>;
8597 APSR.Z = IsZeroBit(result);
8598 APSR.C = carry;
8599 APSR.V = overflow;
8600 #endif
8601
8602 bool success = false;
8603
8604 uint32_t Rd; // the destination register
8605 uint32_t Rn; // the first operand
8606 bool setflags;
8607 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8608 switch (encoding) {
8609 case eEncodingT1:
8610 Rd = Bits32(opcode, 2, 0);
8611 Rn = Bits32(opcode, 5, 3);
8612 setflags = !InITBlock();
8613 imm32 = 0;
8614 break;
8615 case eEncodingT2:
8616 Rd = Bits32(opcode, 11, 8);
8617 Rn = Bits32(opcode, 19, 16);
8618 setflags = BitIsSet(opcode, 20);
8619 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8620 if (BadReg(Rd) || BadReg(Rn))
8621 return false;
8622 break;
8623 case eEncodingA1:
8624 Rd = Bits32(opcode, 15, 12);
8625 Rn = Bits32(opcode, 19, 16);
8626 setflags = BitIsSet(opcode, 20);
8627 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8628
8629 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8630 if (Rd == 15 && setflags)
8631 return EmulateSUBSPcLrEtc (opcode, encoding);
8632 break;
8633 default:
8634 return false;
8635 }
8636 // Read the register value from the operand register Rn.
8637 uint32_t reg_val = ReadCoreReg(Rn, &success);
8638 if (!success)
8639 return false;
8640
8641 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8642
8643 EmulateInstruction::Context context;
8644 context.type = EmulateInstruction::eContextImmediate;
8645 context.SetNoArgs ();
8646
8647 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8648 return false;
8649
8650 return true;
8651 }
8652
8653 // Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8654 // result to the destination register. It can optionally update the condition flags based on the result.
8655 bool
EmulateRSBReg(const uint32_t opcode,const ARMEncoding encoding)8656 EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
8657 {
8658 #if 0
8659 // ARM pseudo code...
8660 if ConditionPassed() then
8661 EncodingSpecificOperations();
8662 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8663 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8664 if d == 15 then // Can only occur for ARM encoding
8665 ALUWritePC(result); // setflags is always FALSE here
8666 else
8667 R[d] = result;
8668 if setflags then
8669 APSR.N = result<31>;
8670 APSR.Z = IsZeroBit(result);
8671 APSR.C = carry;
8672 APSR.V = overflow;
8673 #endif
8674
8675 bool success = false;
8676
8677 uint32_t Rd; // the destination register
8678 uint32_t Rn; // the first operand
8679 uint32_t Rm; // the second operand
8680 bool setflags;
8681 ARM_ShifterType shift_t;
8682 uint32_t shift_n; // the shift applied to the value read from Rm
8683 switch (encoding) {
8684 case eEncodingT1:
8685 Rd = Bits32(opcode, 11, 8);
8686 Rn = Bits32(opcode, 19, 16);
8687 Rm = Bits32(opcode, 3, 0);
8688 setflags = BitIsSet(opcode, 20);
8689 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8690 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8691 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8692 return false;
8693 break;
8694 case eEncodingA1:
8695 Rd = Bits32(opcode, 15, 12);
8696 Rn = Bits32(opcode, 19, 16);
8697 Rm = Bits32(opcode, 3, 0);
8698 setflags = BitIsSet(opcode, 20);
8699 shift_n = DecodeImmShiftARM(opcode, shift_t);
8700
8701 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8702 if (Rd == 15 && setflags)
8703 return EmulateSUBSPcLrEtc (opcode, encoding);
8704 break;
8705 default:
8706 return false;
8707 }
8708 // Read the register value from register Rn.
8709 uint32_t val1 = ReadCoreReg(Rn, &success);
8710 if (!success)
8711 return false;
8712
8713 // Read the register value from register Rm.
8714 uint32_t val2 = ReadCoreReg(Rm, &success);
8715 if (!success)
8716 return false;
8717
8718 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8719 if (!success)
8720 return false;
8721 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8722
8723 EmulateInstruction::Context context;
8724 context.type = EmulateInstruction::eContextImmediate;
8725 context.SetNoArgs();
8726 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8727 return false;
8728
8729 return true;
8730 }
8731
8732 // Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8733 // an immediate value, and writes the result to the destination register. It can optionally update the condition
8734 // flags based on the result.
8735 bool
EmulateRSCImm(const uint32_t opcode,const ARMEncoding encoding)8736 EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
8737 {
8738 #if 0
8739 // ARM pseudo code...
8740 if ConditionPassed() then
8741 EncodingSpecificOperations();
8742 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8743 if d == 15 then
8744 ALUWritePC(result); // setflags is always FALSE here
8745 else
8746 R[d] = result;
8747 if setflags then
8748 APSR.N = result<31>;
8749 APSR.Z = IsZeroBit(result);
8750 APSR.C = carry;
8751 APSR.V = overflow;
8752 #endif
8753
8754 bool success = false;
8755
8756 uint32_t Rd; // the destination register
8757 uint32_t Rn; // the first operand
8758 bool setflags;
8759 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8760 switch (encoding) {
8761 case eEncodingA1:
8762 Rd = Bits32(opcode, 15, 12);
8763 Rn = Bits32(opcode, 19, 16);
8764 setflags = BitIsSet(opcode, 20);
8765 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8766
8767 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8768 if (Rd == 15 && setflags)
8769 return EmulateSUBSPcLrEtc (opcode, encoding);
8770 break;
8771 default:
8772 return false;
8773 }
8774 // Read the register value from the operand register Rn.
8775 uint32_t reg_val = ReadCoreReg(Rn, &success);
8776 if (!success)
8777 return false;
8778
8779 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8780
8781 EmulateInstruction::Context context;
8782 context.type = EmulateInstruction::eContextImmediate;
8783 context.SetNoArgs ();
8784
8785 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8786 return false;
8787
8788 return true;
8789 }
8790
8791 // Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8792 // optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8793 // condition flags based on the result.
8794 bool
EmulateRSCReg(const uint32_t opcode,const ARMEncoding encoding)8795 EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
8796 {
8797 #if 0
8798 // ARM pseudo code...
8799 if ConditionPassed() then
8800 EncodingSpecificOperations();
8801 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8802 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8803 if d == 15 then
8804 ALUWritePC(result); // setflags is always FALSE here
8805 else
8806 R[d] = result;
8807 if setflags then
8808 APSR.N = result<31>;
8809 APSR.Z = IsZeroBit(result);
8810 APSR.C = carry;
8811 APSR.V = overflow;
8812 #endif
8813
8814 bool success = false;
8815
8816 uint32_t Rd; // the destination register
8817 uint32_t Rn; // the first operand
8818 uint32_t Rm; // the second operand
8819 bool setflags;
8820 ARM_ShifterType shift_t;
8821 uint32_t shift_n; // the shift applied to the value read from Rm
8822 switch (encoding) {
8823 case eEncodingA1:
8824 Rd = Bits32(opcode, 15, 12);
8825 Rn = Bits32(opcode, 19, 16);
8826 Rm = Bits32(opcode, 3, 0);
8827 setflags = BitIsSet(opcode, 20);
8828 shift_n = DecodeImmShiftARM(opcode, shift_t);
8829
8830 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8831 if (Rd == 15 && setflags)
8832 return EmulateSUBSPcLrEtc (opcode, encoding);
8833 break;
8834 default:
8835 return false;
8836 }
8837 // Read the register value from register Rn.
8838 uint32_t val1 = ReadCoreReg(Rn, &success);
8839 if (!success)
8840 return false;
8841
8842 // Read the register value from register Rm.
8843 uint32_t val2 = ReadCoreReg(Rm, &success);
8844 if (!success)
8845 return false;
8846
8847 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8848 if (!success)
8849 return false;
8850 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8851
8852 EmulateInstruction::Context context;
8853 context.type = EmulateInstruction::eContextImmediate;
8854 context.SetNoArgs();
8855 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8856 return false;
8857
8858 return true;
8859 }
8860
8861 // Subtract with Carry (immediate) subtracts an immediate value and the value of
8862 // NOT (Carry flag) from a register value, and writes the result to the destination register.
8863 // It can optionally update the condition flags based on the result.
8864 bool
EmulateSBCImm(const uint32_t opcode,const ARMEncoding encoding)8865 EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
8866 {
8867 #if 0
8868 // ARM pseudo code...
8869 if ConditionPassed() then
8870 EncodingSpecificOperations();
8871 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
8872 if d == 15 then // Can only occur for ARM encoding
8873 ALUWritePC(result); // setflags is always FALSE here
8874 else
8875 R[d] = result;
8876 if setflags then
8877 APSR.N = result<31>;
8878 APSR.Z = IsZeroBit(result);
8879 APSR.C = carry;
8880 APSR.V = overflow;
8881 #endif
8882
8883 bool success = false;
8884
8885 uint32_t Rd; // the destination register
8886 uint32_t Rn; // the first operand
8887 bool setflags;
8888 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8889 switch (encoding) {
8890 case eEncodingT1:
8891 Rd = Bits32(opcode, 11, 8);
8892 Rn = Bits32(opcode, 19, 16);
8893 setflags = BitIsSet(opcode, 20);
8894 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8895 if (BadReg(Rd) || BadReg(Rn))
8896 return false;
8897 break;
8898 case eEncodingA1:
8899 Rd = Bits32(opcode, 15, 12);
8900 Rn = Bits32(opcode, 19, 16);
8901 setflags = BitIsSet(opcode, 20);
8902 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8903
8904 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8905 if (Rd == 15 && setflags)
8906 return EmulateSUBSPcLrEtc (opcode, encoding);
8907 break;
8908 default:
8909 return false;
8910 }
8911 // Read the register value from the operand register Rn.
8912 uint32_t reg_val = ReadCoreReg(Rn, &success);
8913 if (!success)
8914 return false;
8915
8916 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8917
8918 EmulateInstruction::Context context;
8919 context.type = EmulateInstruction::eContextImmediate;
8920 context.SetNoArgs ();
8921
8922 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8923 return false;
8924
8925 return true;
8926 }
8927
8928 // Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8929 // NOT (Carry flag) from a register value, and writes the result to the destination register.
8930 // It can optionally update the condition flags based on the result.
8931 bool
EmulateSBCReg(const uint32_t opcode,const ARMEncoding encoding)8932 EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
8933 {
8934 #if 0
8935 // ARM pseudo code...
8936 if ConditionPassed() then
8937 EncodingSpecificOperations();
8938 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8939 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8940 if d == 15 then // Can only occur for ARM encoding
8941 ALUWritePC(result); // setflags is always FALSE here
8942 else
8943 R[d] = result;
8944 if setflags then
8945 APSR.N = result<31>;
8946 APSR.Z = IsZeroBit(result);
8947 APSR.C = carry;
8948 APSR.V = overflow;
8949 #endif
8950
8951 bool success = false;
8952
8953 uint32_t Rd; // the destination register
8954 uint32_t Rn; // the first operand
8955 uint32_t Rm; // the second operand
8956 bool setflags;
8957 ARM_ShifterType shift_t;
8958 uint32_t shift_n; // the shift applied to the value read from Rm
8959 switch (encoding) {
8960 case eEncodingT1:
8961 Rd = Rn = Bits32(opcode, 2, 0);
8962 Rm = Bits32(opcode, 5, 3);
8963 setflags = !InITBlock();
8964 shift_t = SRType_LSL;
8965 shift_n = 0;
8966 break;
8967 case eEncodingT2:
8968 Rd = Bits32(opcode, 11, 8);
8969 Rn = Bits32(opcode, 19, 16);
8970 Rm = Bits32(opcode, 3, 0);
8971 setflags = BitIsSet(opcode, 20);
8972 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8973 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8974 return false;
8975 break;
8976 case eEncodingA1:
8977 Rd = Bits32(opcode, 15, 12);
8978 Rn = Bits32(opcode, 19, 16);
8979 Rm = Bits32(opcode, 3, 0);
8980 setflags = BitIsSet(opcode, 20);
8981 shift_n = DecodeImmShiftARM(opcode, shift_t);
8982
8983 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8984 if (Rd == 15 && setflags)
8985 return EmulateSUBSPcLrEtc (opcode, encoding);
8986 break;
8987 default:
8988 return false;
8989 }
8990 // Read the register value from register Rn.
8991 uint32_t val1 = ReadCoreReg(Rn, &success);
8992 if (!success)
8993 return false;
8994
8995 // Read the register value from register Rm.
8996 uint32_t val2 = ReadCoreReg(Rm, &success);
8997 if (!success)
8998 return false;
8999
9000 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9001 if (!success)
9002 return false;
9003 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9004
9005 EmulateInstruction::Context context;
9006 context.type = EmulateInstruction::eContextImmediate;
9007 context.SetNoArgs();
9008 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9009 return false;
9010
9011 return true;
9012 }
9013
9014 // This instruction subtracts an immediate value from a register value, and writes the result
9015 // to the destination register. It can optionally update the condition flags based on the result.
9016 bool
EmulateSUBImmThumb(const uint32_t opcode,const ARMEncoding encoding)9017 EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
9018 {
9019 #if 0
9020 // ARM pseudo code...
9021 if ConditionPassed() then
9022 EncodingSpecificOperations();
9023 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9024 R[d] = result;
9025 if setflags then
9026 APSR.N = result<31>;
9027 APSR.Z = IsZeroBit(result);
9028 APSR.C = carry;
9029 APSR.V = overflow;
9030 #endif
9031
9032 bool success = false;
9033
9034 uint32_t Rd; // the destination register
9035 uint32_t Rn; // the first operand
9036 bool setflags;
9037 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9038 switch (encoding) {
9039 case eEncodingT1:
9040 Rd = Bits32(opcode, 2, 0);
9041 Rn = Bits32(opcode, 5, 3);
9042 setflags = !InITBlock();
9043 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9044 break;
9045 case eEncodingT2:
9046 Rd = Rn = Bits32(opcode, 10, 8);
9047 setflags = !InITBlock();
9048 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9049 break;
9050 case eEncodingT3:
9051 Rd = Bits32(opcode, 11, 8);
9052 Rn = Bits32(opcode, 19, 16);
9053 setflags = BitIsSet(opcode, 20);
9054 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9055
9056 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9057 if (Rd == 15 && setflags)
9058 return EmulateCMPImm (opcode, eEncodingT2);
9059
9060 // if Rn == '1101' then SEE SUB (SP minus immediate);
9061 if (Rn == 13)
9062 return EmulateSUBSPImm (opcode, eEncodingT2);
9063
9064 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9065 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9066 return false;
9067 break;
9068 case eEncodingT4:
9069 Rd = Bits32(opcode, 11, 8);
9070 Rn = Bits32(opcode, 19, 16);
9071 setflags = BitIsSet(opcode, 20);
9072 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9073
9074 // if Rn == '1111' then SEE ADR;
9075 if (Rn == 15)
9076 return EmulateADR (opcode, eEncodingT2);
9077
9078 // if Rn == '1101' then SEE SUB (SP minus immediate);
9079 if (Rn == 13)
9080 return EmulateSUBSPImm (opcode, eEncodingT3);
9081
9082 if (BadReg(Rd))
9083 return false;
9084 break;
9085 default:
9086 return false;
9087 }
9088 // Read the register value from the operand register Rn.
9089 uint32_t reg_val = ReadCoreReg(Rn, &success);
9090 if (!success)
9091 return false;
9092
9093 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9094
9095 EmulateInstruction::Context context;
9096 context.type = EmulateInstruction::eContextImmediate;
9097 context.SetNoArgs ();
9098
9099 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9100 return false;
9101
9102 return true;
9103 }
9104
9105 // This instruction subtracts an immediate value from a register value, and writes the result
9106 // to the destination register. It can optionally update the condition flags based on the result.
9107 bool
EmulateSUBImmARM(const uint32_t opcode,const ARMEncoding encoding)9108 EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9109 {
9110 #if 0
9111 // ARM pseudo code...
9112 if ConditionPassed() then
9113 EncodingSpecificOperations();
9114 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9115 if d == 15 then
9116 ALUWritePC(result); // setflags is always FALSE here
9117 else
9118 R[d] = result;
9119 if setflags then
9120 APSR.N = result<31>;
9121 APSR.Z = IsZeroBit(result);
9122 APSR.C = carry;
9123 APSR.V = overflow;
9124 #endif
9125
9126 bool success = false;
9127
9128 uint32_t Rd; // the destination register
9129 uint32_t Rn; // the first operand
9130 bool setflags;
9131 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9132 switch (encoding) {
9133 case eEncodingA1:
9134 Rd = Bits32(opcode, 15, 12);
9135 Rn = Bits32(opcode, 19, 16);
9136 setflags = BitIsSet(opcode, 20);
9137 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9138
9139 // if Rn == '1111' && S == '0' then SEE ADR;
9140 if (Rn == 15 && !setflags)
9141 return EmulateADR (opcode, eEncodingA2);
9142
9143 // if Rn == '1101' then SEE SUB (SP minus immediate);
9144 if (Rn == 13)
9145 return EmulateSUBSPImm (opcode, eEncodingA1);
9146
9147 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9148 if (Rd == 15 && setflags)
9149 return EmulateSUBSPcLrEtc (opcode, encoding);
9150 break;
9151 default:
9152 return false;
9153 }
9154 // Read the register value from the operand register Rn.
9155 uint32_t reg_val = ReadCoreReg(Rn, &success);
9156 if (!success)
9157 return false;
9158
9159 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9160
9161 EmulateInstruction::Context context;
9162 context.type = EmulateInstruction::eContextImmediate;
9163 context.SetNoArgs ();
9164
9165 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9166 return false;
9167
9168 return true;
9169 }
9170
9171 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9172 // immediate value. It updates the condition flags based on the result, and discards the result.
9173 bool
EmulateTEQImm(const uint32_t opcode,const ARMEncoding encoding)9174 EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
9175 {
9176 #if 0
9177 // ARM pseudo code...
9178 if ConditionPassed() then
9179 EncodingSpecificOperations();
9180 result = R[n] EOR imm32;
9181 APSR.N = result<31>;
9182 APSR.Z = IsZeroBit(result);
9183 APSR.C = carry;
9184 // APSR.V unchanged
9185 #endif
9186
9187 bool success = false;
9188
9189 if (ConditionPassed(opcode))
9190 {
9191 uint32_t Rn;
9192 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9193 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9194 switch (encoding)
9195 {
9196 case eEncodingT1:
9197 Rn = Bits32(opcode, 19, 16);
9198 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9199 if (BadReg(Rn))
9200 return false;
9201 break;
9202 case eEncodingA1:
9203 Rn = Bits32(opcode, 19, 16);
9204 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9205 break;
9206 default:
9207 return false;
9208 }
9209
9210 // Read the first operand.
9211 uint32_t val1 = ReadCoreReg(Rn, &success);
9212 if (!success)
9213 return false;
9214
9215 uint32_t result = val1 ^ imm32;
9216
9217 EmulateInstruction::Context context;
9218 context.type = EmulateInstruction::eContextImmediate;
9219 context.SetNoArgs ();
9220
9221 if (!WriteFlags(context, result, carry))
9222 return false;
9223 }
9224 return true;
9225 }
9226
9227 // Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9228 // optionally-shifted register value. It updates the condition flags based on the result, and discards
9229 // the result.
9230 bool
EmulateTEQReg(const uint32_t opcode,const ARMEncoding encoding)9231 EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
9232 {
9233 #if 0
9234 // ARM pseudo code...
9235 if ConditionPassed() then
9236 EncodingSpecificOperations();
9237 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9238 result = R[n] EOR shifted;
9239 APSR.N = result<31>;
9240 APSR.Z = IsZeroBit(result);
9241 APSR.C = carry;
9242 // APSR.V unchanged
9243 #endif
9244
9245 bool success = false;
9246
9247 if (ConditionPassed(opcode))
9248 {
9249 uint32_t Rn, Rm;
9250 ARM_ShifterType shift_t;
9251 uint32_t shift_n; // the shift applied to the value read from Rm
9252 uint32_t carry;
9253 switch (encoding)
9254 {
9255 case eEncodingT1:
9256 Rn = Bits32(opcode, 19, 16);
9257 Rm = Bits32(opcode, 3, 0);
9258 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9259 if (BadReg(Rn) || BadReg(Rm))
9260 return false;
9261 break;
9262 case eEncodingA1:
9263 Rn = Bits32(opcode, 19, 16);
9264 Rm = Bits32(opcode, 3, 0);
9265 shift_n = DecodeImmShiftARM(opcode, shift_t);
9266 break;
9267 default:
9268 return false;
9269 }
9270
9271 // Read the first operand.
9272 uint32_t val1 = ReadCoreReg(Rn, &success);
9273 if (!success)
9274 return false;
9275
9276 // Read the second operand.
9277 uint32_t val2 = ReadCoreReg(Rm, &success);
9278 if (!success)
9279 return false;
9280
9281 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9282 if (!success)
9283 return false;
9284 uint32_t result = val1 ^ shifted;
9285
9286 EmulateInstruction::Context context;
9287 context.type = EmulateInstruction::eContextImmediate;
9288 context.SetNoArgs ();
9289
9290 if (!WriteFlags(context, result, carry))
9291 return false;
9292 }
9293 return true;
9294 }
9295
9296 // Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9297 // It updates the condition flags based on the result, and discards the result.
9298 bool
EmulateTSTImm(const uint32_t opcode,const ARMEncoding encoding)9299 EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
9300 {
9301 #if 0
9302 // ARM pseudo code...
9303 if ConditionPassed() then
9304 EncodingSpecificOperations();
9305 result = R[n] AND imm32;
9306 APSR.N = result<31>;
9307 APSR.Z = IsZeroBit(result);
9308 APSR.C = carry;
9309 // APSR.V unchanged
9310 #endif
9311
9312 bool success = false;
9313
9314 if (ConditionPassed(opcode))
9315 {
9316 uint32_t Rn;
9317 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9318 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9319 switch (encoding)
9320 {
9321 case eEncodingT1:
9322 Rn = Bits32(opcode, 19, 16);
9323 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9324 if (BadReg(Rn))
9325 return false;
9326 break;
9327 case eEncodingA1:
9328 Rn = Bits32(opcode, 19, 16);
9329 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9330 break;
9331 default:
9332 return false;
9333 }
9334
9335 // Read the first operand.
9336 uint32_t val1 = ReadCoreReg(Rn, &success);
9337 if (!success)
9338 return false;
9339
9340 uint32_t result = val1 & imm32;
9341
9342 EmulateInstruction::Context context;
9343 context.type = EmulateInstruction::eContextImmediate;
9344 context.SetNoArgs ();
9345
9346 if (!WriteFlags(context, result, carry))
9347 return false;
9348 }
9349 return true;
9350 }
9351
9352 // Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9353 // It updates the condition flags based on the result, and discards the result.
9354 bool
EmulateTSTReg(const uint32_t opcode,const ARMEncoding encoding)9355 EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
9356 {
9357 #if 0
9358 // ARM pseudo code...
9359 if ConditionPassed() then
9360 EncodingSpecificOperations();
9361 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9362 result = R[n] AND shifted;
9363 APSR.N = result<31>;
9364 APSR.Z = IsZeroBit(result);
9365 APSR.C = carry;
9366 // APSR.V unchanged
9367 #endif
9368
9369 bool success = false;
9370
9371 if (ConditionPassed(opcode))
9372 {
9373 uint32_t Rn, Rm;
9374 ARM_ShifterType shift_t;
9375 uint32_t shift_n; // the shift applied to the value read from Rm
9376 uint32_t carry;
9377 switch (encoding)
9378 {
9379 case eEncodingT1:
9380 Rn = Bits32(opcode, 2, 0);
9381 Rm = Bits32(opcode, 5, 3);
9382 shift_t = SRType_LSL;
9383 shift_n = 0;
9384 break;
9385 case eEncodingT2:
9386 Rn = Bits32(opcode, 19, 16);
9387 Rm = Bits32(opcode, 3, 0);
9388 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9389 if (BadReg(Rn) || BadReg(Rm))
9390 return false;
9391 break;
9392 case eEncodingA1:
9393 Rn = Bits32(opcode, 19, 16);
9394 Rm = Bits32(opcode, 3, 0);
9395 shift_n = DecodeImmShiftARM(opcode, shift_t);
9396 break;
9397 default:
9398 return false;
9399 }
9400
9401 // Read the first operand.
9402 uint32_t val1 = ReadCoreReg(Rn, &success);
9403 if (!success)
9404 return false;
9405
9406 // Read the second operand.
9407 uint32_t val2 = ReadCoreReg(Rm, &success);
9408 if (!success)
9409 return false;
9410
9411 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9412 if (!success)
9413 return false;
9414 uint32_t result = val1 & shifted;
9415
9416 EmulateInstruction::Context context;
9417 context.type = EmulateInstruction::eContextImmediate;
9418 context.SetNoArgs ();
9419
9420 if (!WriteFlags(context, result, carry))
9421 return false;
9422 }
9423 return true;
9424 }
9425
9426 // A8.6.216 SUB (SP minus register)
9427 bool
EmulateSUBSPReg(const uint32_t opcode,const ARMEncoding encoding)9428 EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9429 {
9430 #if 0
9431 if ConditionPassed() then
9432 EncodingSpecificOperations();
9433 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9434 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
9435 if d == 15 then // Can only occur for ARM encoding
9436 ALUWritePC(result); // setflags is always FALSE here
9437 else
9438 R[d] = result;
9439 if setflags then
9440 APSR.N = result<31>;
9441 APSR.Z = IsZeroBit(result);
9442 APSR.C = carry;
9443 APSR.V = overflow;
9444 #endif
9445
9446 bool success = false;
9447
9448 if (ConditionPassed(opcode))
9449 {
9450 uint32_t d;
9451 uint32_t m;
9452 bool setflags;
9453 ARM_ShifterType shift_t;
9454 uint32_t shift_n;
9455
9456 switch (encoding)
9457 {
9458 case eEncodingT1:
9459 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
9460 d = Bits32 (opcode, 11, 8);
9461 m = Bits32 (opcode, 3, 0);
9462 setflags = BitIsSet (opcode, 20);
9463
9464 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9465 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9466
9467 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9468 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9469 return false;
9470
9471 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9472 if ((d == 15) || BadReg (m))
9473 return false;
9474 break;
9475
9476 case eEncodingA1:
9477 // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
9478 d = Bits32 (opcode, 15, 12);
9479 m = Bits32 (opcode, 3, 0);
9480 setflags = BitIsSet (opcode, 20);
9481
9482 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
9483 if (d == 15 && setflags)
9484 EmulateSUBSPcLrEtc (opcode, encoding);
9485
9486 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9487 shift_n = DecodeImmShiftARM (opcode, shift_t);
9488 break;
9489
9490 default:
9491 return false;
9492 }
9493
9494 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9495 uint32_t Rm = ReadCoreReg (m, &success);
9496 if (!success)
9497 return false;
9498
9499 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9500 if (!success)
9501 return false;
9502
9503 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
9504 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9505 if (!success)
9506 return false;
9507
9508 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9509
9510 EmulateInstruction::Context context;
9511 context.type = eContextArithmetic;
9512 RegisterInfo sp_reg;
9513 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9514 RegisterInfo dwarf_reg;
9515 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
9516 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9517
9518 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
9519 return false;
9520 }
9521 return true;
9522 }
9523
9524
9525 // A8.6.7 ADD (register-shifted register)
9526 bool
EmulateADDRegShift(const uint32_t opcode,const ARMEncoding encoding)9527 EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
9528 {
9529 #if 0
9530 if ConditionPassed() then
9531 EncodingSpecificOperations();
9532 shift_n = UInt(R[s]<7:0>);
9533 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9534 (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
9535 R[d] = result;
9536 if setflags then
9537 APSR.N = result<31>;
9538 APSR.Z = IsZeroBit(result);
9539 APSR.C = carry;
9540 APSR.V = overflow;
9541 #endif
9542
9543 bool success = false;
9544
9545 if (ConditionPassed(opcode))
9546 {
9547 uint32_t d;
9548 uint32_t n;
9549 uint32_t m;
9550 uint32_t s;
9551 bool setflags;
9552 ARM_ShifterType shift_t;
9553
9554 switch (encoding)
9555 {
9556 case eEncodingA1:
9557 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9558 d = Bits32 (opcode, 15, 12);
9559 n = Bits32 (opcode, 19, 16);
9560 m = Bits32 (opcode, 3, 0);
9561 s = Bits32 (opcode, 11, 8);
9562
9563 // setflags = (S == �1�); shift_t = DecodeRegShift(type);
9564 setflags = BitIsSet (opcode, 20);
9565 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9566
9567 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9568 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9569 return false;
9570 break;
9571
9572 default:
9573 return false;
9574 }
9575
9576 // shift_n = UInt(R[s]<7:0>);
9577 uint32_t Rs = ReadCoreReg (s, &success);
9578 if (!success)
9579 return false;
9580
9581 uint32_t shift_n = Bits32 (Rs, 7, 0);
9582
9583 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9584 uint32_t Rm = ReadCoreReg (m, &success);
9585 if (!success)
9586 return false;
9587
9588 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9589 if (!success)
9590 return false;
9591
9592 // (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
9593 uint32_t Rn = ReadCoreReg (n, &success);
9594 if (!success)
9595 return false;
9596
9597 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9598
9599 // R[d] = result;
9600 EmulateInstruction::Context context;
9601 context.type = eContextArithmetic;
9602 RegisterInfo reg_n;
9603 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9604 RegisterInfo reg_m;
9605 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9606
9607 context.SetRegisterRegisterOperands (reg_n, reg_m);
9608
9609 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9610 return false;
9611
9612 // if setflags then
9613 // APSR.N = result<31>;
9614 // APSR.Z = IsZeroBit(result);
9615 // APSR.C = carry;
9616 // APSR.V = overflow;
9617 if (setflags)
9618 return WriteFlags (context, res.result, res.carry_out, res.overflow);
9619 }
9620 return true;
9621 }
9622
9623 // A8.6.213 SUB (register)
9624 bool
EmulateSUBReg(const uint32_t opcode,const ARMEncoding encoding)9625 EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9626 {
9627 #if 0
9628 if ConditionPassed() then
9629 EncodingSpecificOperations();
9630 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9631 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
9632 if d == 15 then // Can only occur for ARM encoding
9633 ALUWritePC(result); // setflags is always FALSE here
9634 else
9635 R[d] = result;
9636 if setflags then
9637 APSR.N = result<31>;
9638 APSR.Z = IsZeroBit(result);
9639 APSR.C = carry;
9640 APSR.V = overflow;
9641 #endif
9642
9643 bool success = false;
9644
9645 if (ConditionPassed(opcode))
9646 {
9647 uint32_t d;
9648 uint32_t n;
9649 uint32_t m;
9650 bool setflags;
9651 ARM_ShifterType shift_t;
9652 uint32_t shift_n;
9653
9654 switch (encoding)
9655 {
9656 case eEncodingT1:
9657 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9658 d = Bits32 (opcode, 2, 0);
9659 n = Bits32 (opcode, 5, 3);
9660 m = Bits32 (opcode, 8, 6);
9661 setflags = !InITBlock();
9662
9663 // (shift_t, shift_n) = (SRType_LSL, 0);
9664 shift_t = SRType_LSL;
9665 shift_n = 0;
9666
9667 break;
9668
9669 case eEncodingT2:
9670 // if Rd == �1111� && S == �1� then SEE CMP (register);
9671 // if Rn == �1101� then SEE SUB (SP minus register);
9672 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
9673 d = Bits32 (opcode, 11, 8);
9674 n = Bits32 (opcode, 19, 16);
9675 m = Bits32 (opcode, 3, 0);
9676 setflags = BitIsSet (opcode, 20);
9677
9678 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9679 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9680
9681 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9682 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9683 return false;
9684
9685 break;
9686
9687 case eEncodingA1:
9688 // if Rn == �1101� then SEE SUB (SP minus register);
9689 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
9690 d = Bits32 (opcode, 15, 12);
9691 n = Bits32 (opcode, 19, 16);
9692 m = Bits32 (opcode, 3, 0);
9693 setflags = BitIsSet (opcode, 20);
9694
9695 // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
9696 if ((d == 15) && setflags)
9697 EmulateSUBSPcLrEtc (opcode, encoding);
9698
9699 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9700 shift_n = DecodeImmShiftARM (opcode, shift_t);
9701
9702 break;
9703
9704 default:
9705 return false;
9706 }
9707
9708 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9709 uint32_t Rm = ReadCoreReg (m, &success);
9710 if (!success)
9711 return false;
9712
9713 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9714 if (!success)
9715 return false;
9716
9717 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
9718 uint32_t Rn = ReadCoreReg (n, &success);
9719 if (!success)
9720 return false;
9721
9722 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9723
9724 // if d == 15 then // Can only occur for ARM encoding
9725 // ALUWritePC(result); // setflags is always FALSE here
9726 // else
9727 // R[d] = result;
9728 // if setflags then
9729 // APSR.N = result<31>;
9730 // APSR.Z = IsZeroBit(result);
9731 // APSR.C = carry;
9732 // APSR.V = overflow;
9733
9734 EmulateInstruction::Context context;
9735 context.type = eContextArithmetic;
9736 RegisterInfo reg_n;
9737 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9738 RegisterInfo reg_m;
9739 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
9740 context.SetRegisterRegisterOperands (reg_n, reg_m);
9741
9742 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
9743 return false;
9744 }
9745 return true;
9746 }
9747
9748 // A8.6.202 STREX
9749 // Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9750 // word from a register to memory if the executing processor has exclusive access to the memory addressed.
9751 bool
EmulateSTREX(const uint32_t opcode,const ARMEncoding encoding)9752 EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9753 {
9754 #if 0
9755 if ConditionPassed() then
9756 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9757 address = R[n] + imm32;
9758 if ExclusiveMonitorsPass(address,4) then
9759 MemA[address,4] = R[t];
9760 R[d] = 0;
9761 else
9762 R[d] = 1;
9763 #endif
9764
9765 bool success = false;
9766
9767 if (ConditionPassed(opcode))
9768 {
9769 uint32_t d;
9770 uint32_t t;
9771 uint32_t n;
9772 uint32_t imm32;
9773 const uint32_t addr_byte_size = GetAddressByteSize();
9774
9775 switch (encoding)
9776 {
9777 case eEncodingT1:
9778 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
9779 d = Bits32 (opcode, 11, 8);
9780 t = Bits32 (opcode, 15, 12);
9781 n = Bits32 (opcode, 19, 16);
9782 imm32 = Bits32 (opcode, 7, 0) << 2;
9783
9784 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9785 if (BadReg (d) || BadReg (t) || (n == 15))
9786 return false;
9787
9788 // if d == n || d == t then UNPREDICTABLE;
9789 if ((d == n) || (d == t))
9790 return false;
9791
9792 break;
9793
9794 case eEncodingA1:
9795 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9796 d = Bits32 (opcode, 15, 12);
9797 t = Bits32 (opcode, 3, 0);
9798 n = Bits32 (opcode, 19, 16);
9799 imm32 = 0;
9800
9801 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9802 if ((d == 15) || (t == 15) || (n == 15))
9803 return false;
9804
9805 // if d == n || d == t then UNPREDICTABLE;
9806 if ((d == n) || (d == t))
9807 return false;
9808
9809 break;
9810
9811 default:
9812 return false;
9813 }
9814
9815 // address = R[n] + imm32;
9816 uint32_t Rn = ReadCoreReg (n, &success);
9817 if (!success)
9818 return false;
9819
9820 addr_t address = Rn + imm32;
9821
9822 RegisterInfo base_reg;
9823 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9824 RegisterInfo data_reg;
9825 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
9826 EmulateInstruction::Context context;
9827 context.type = eContextRegisterStore;
9828 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9829
9830 // if ExclusiveMonitorsPass(address,4) then
9831 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9832 // always return true.
9833 if (true)
9834 {
9835 // MemA[address,4] = R[t];
9836 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9837 if (!success)
9838 return false;
9839
9840 if (!MemAWrite (context, address, Rt, addr_byte_size))
9841 return false;
9842
9843 // R[d] = 0;
9844 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9845 return false;
9846 }
9847 else
9848 {
9849 // R[d] = 1;
9850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9851 return false;
9852 }
9853 }
9854 return true;
9855 }
9856
9857 // A8.6.197 STRB (immediate, ARM)
9858 bool
EmulateSTRBImmARM(const uint32_t opcode,const ARMEncoding encoding)9859 EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9860 {
9861 #if 0
9862 if ConditionPassed() then
9863 EncodingSpecificOperations();
9864 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9865 address = if index then offset_addr else R[n];
9866 MemU[address,1] = R[t]<7:0>;
9867 if wback then R[n] = offset_addr;
9868 #endif
9869
9870 bool success = false;
9871
9872 if (ConditionPassed(opcode))
9873 {
9874 uint32_t t;
9875 uint32_t n;
9876 uint32_t imm32;
9877 bool index;
9878 bool add;
9879 bool wback;
9880
9881 switch (encoding)
9882 {
9883 case eEncodingA1:
9884 // if P == �0� && W == �1� then SEE STRBT;
9885 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9886 t = Bits32 (opcode, 15, 12);
9887 n = Bits32 (opcode, 19, 16);
9888 imm32 = Bits32 (opcode, 11, 0);
9889
9890 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
9891 index = BitIsSet (opcode, 24);
9892 add = BitIsSet (opcode, 23);
9893 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9894
9895 // if t == 15 then UNPREDICTABLE;
9896 if (t == 15)
9897 return false;
9898
9899 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9900 if (wback && ((n == 15) || (n == t)))
9901 return false;
9902
9903 break;
9904
9905 default:
9906 return false;
9907 }
9908
9909 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9910 uint32_t Rn = ReadCoreReg (n, &success);
9911 if (!success)
9912 return false;
9913
9914 addr_t offset_addr;
9915 if (add)
9916 offset_addr = Rn + imm32;
9917 else
9918 offset_addr = Rn - imm32;
9919
9920 // address = if index then offset_addr else R[n];
9921 addr_t address;
9922 if (index)
9923 address = offset_addr;
9924 else
9925 address = Rn;
9926
9927 // MemU[address,1] = R[t]<7:0>;
9928 uint32_t Rt = ReadCoreReg (t, &success);
9929 if (!success)
9930 return false;
9931
9932 RegisterInfo base_reg;
9933 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9934 RegisterInfo data_reg;
9935 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
9936 EmulateInstruction::Context context;
9937 context.type = eContextRegisterStore;
9938 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9939
9940 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9941 return false;
9942
9943 // if wback then R[n] = offset_addr;
9944 if (wback)
9945 {
9946 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9947 return false;
9948 }
9949 }
9950 return true;
9951 }
9952
9953 // A8.6.194 STR (immediate, ARM)
9954 bool
EmulateSTRImmARM(const uint32_t opcode,const ARMEncoding encoding)9955 EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9956 {
9957 #if 0
9958 if ConditionPassed() then
9959 EncodingSpecificOperations();
9960 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9961 address = if index then offset_addr else R[n];
9962 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9963 if wback then R[n] = offset_addr;
9964 #endif
9965
9966 bool success = false;
9967
9968 if (ConditionPassed(opcode))
9969 {
9970 uint32_t t;
9971 uint32_t n;
9972 uint32_t imm32;
9973 bool index;
9974 bool add;
9975 bool wback;
9976
9977 const uint32_t addr_byte_size = GetAddressByteSize();
9978
9979 switch (encoding)
9980 {
9981 case eEncodingA1:
9982 // if P == �0� && W == �1� then SEE STRT;
9983 // if Rn == �1101� && P == �1� && U == �0� && W == �1� && imm12 == �000000000100� then SEE PUSH;
9984 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9985 t = Bits32 (opcode, 15, 12);
9986 n = Bits32 (opcode, 19, 16);
9987 imm32 = Bits32 (opcode, 11, 0);
9988
9989 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
9990 index = BitIsSet (opcode, 24);
9991 add = BitIsSet (opcode, 23);
9992 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9993
9994 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9995 if (wback && ((n == 15) || (n == t)))
9996 return false;
9997
9998 break;
9999
10000 default:
10001 return false;
10002 }
10003
10004 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10005 uint32_t Rn = ReadCoreReg (n, &success);
10006 if (!success)
10007 return false;
10008
10009 addr_t offset_addr;
10010 if (add)
10011 offset_addr = Rn + imm32;
10012 else
10013 offset_addr = Rn - imm32;
10014
10015 // address = if index then offset_addr else R[n];
10016 addr_t address;
10017 if (index)
10018 address = offset_addr;
10019 else
10020 address = Rn;
10021
10022 RegisterInfo base_reg;
10023 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10024 RegisterInfo data_reg;
10025 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10026 EmulateInstruction::Context context;
10027 context.type = eContextRegisterStore;
10028 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10029
10030 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10031 uint32_t Rt = ReadCoreReg (t, &success);
10032 if (!success)
10033 return false;
10034
10035 if (t == 15)
10036 {
10037 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
10038 if (!success)
10039 return false;
10040
10041 if (!MemUWrite (context, address, pc_value, addr_byte_size))
10042 return false;
10043 }
10044 else
10045 {
10046 if (!MemUWrite (context, address, Rt, addr_byte_size))
10047 return false;
10048 }
10049
10050 // if wback then R[n] = offset_addr;
10051 if (wback)
10052 {
10053 context.type = eContextAdjustBaseRegister;
10054 context.SetImmediate (offset_addr);
10055
10056 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10057 return false;
10058 }
10059 }
10060 return true;
10061 }
10062
10063 // A8.6.66 LDRD (immediate)
10064 // Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10065 // words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
10066 bool
EmulateLDRDImmediate(const uint32_t opcode,const ARMEncoding encoding)10067 EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10068 {
10069 #if 0
10070 if ConditionPassed() then
10071 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10072 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10073 address = if index then offset_addr else R[n];
10074 R[t] = MemA[address,4];
10075 R[t2] = MemA[address+4,4];
10076 if wback then R[n] = offset_addr;
10077 #endif
10078
10079 bool success = false;
10080
10081 if (ConditionPassed(opcode))
10082 {
10083 uint32_t t;
10084 uint32_t t2;
10085 uint32_t n;
10086 uint32_t imm32;
10087 bool index;
10088 bool add;
10089 bool wback;
10090
10091 switch (encoding)
10092 {
10093 case eEncodingT1:
10094 //if P == �0� && W == �0� then SEE �Related encodings�;
10095 //if Rn == �1111� then SEE LDRD (literal);
10096 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10097 t = Bits32 (opcode, 15, 12);
10098 t2 = Bits32 (opcode, 11, 8);
10099 n = Bits32 (opcode, 19, 16);
10100 imm32 = Bits32 (opcode, 7, 0) << 2;
10101
10102 //index = (P == �1�); add = (U == �1�); wback = (W == �1�);
10103 index = BitIsSet (opcode, 24);
10104 add = BitIsSet (opcode, 23);
10105 wback = BitIsSet (opcode, 21);
10106
10107 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10108 if (wback && ((n == t) || (n == t2)))
10109 return false;
10110
10111 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10112 if (BadReg (t) || BadReg (t2) || (t == t2))
10113 return false;
10114
10115 break;
10116
10117 case eEncodingA1:
10118 //if Rn == �1111� then SEE LDRD (literal);
10119 //if Rt<0> == �1� then UNPREDICTABLE;
10120 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10121 t = Bits32 (opcode, 15, 12);
10122 if (BitIsSet (t, 0))
10123 return false;
10124 t2 = t + 1;
10125 n = Bits32 (opcode, 19, 16);
10126 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10127
10128 //index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10129 index = BitIsSet (opcode, 24);
10130 add = BitIsSet (opcode, 23);
10131 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10132
10133 //if P == �0� && W == �1� then UNPREDICTABLE;
10134 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10135 return false;
10136
10137 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10138 if (wback && ((n == t) || (n == t2)))
10139 return false;
10140
10141 //if t2 == 15 then UNPREDICTABLE;
10142 if (t2 == 15)
10143 return false;
10144
10145 break;
10146
10147 default:
10148 return false;
10149 }
10150
10151 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10152 uint32_t Rn = ReadCoreReg (n, &success);
10153 if (!success)
10154 return false;
10155
10156 addr_t offset_addr;
10157 if (add)
10158 offset_addr = Rn + imm32;
10159 else
10160 offset_addr = Rn - imm32;
10161
10162 //address = if index then offset_addr else R[n];
10163 addr_t address;
10164 if (index)
10165 address = offset_addr;
10166 else
10167 address = Rn;
10168
10169 //R[t] = MemA[address,4];
10170 RegisterInfo base_reg;
10171 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10172
10173 EmulateInstruction::Context context;
10174 context.type = eContextRegisterLoad;
10175 context.SetRegisterPlusOffset (base_reg, address - Rn);
10176
10177 const uint32_t addr_byte_size = GetAddressByteSize();
10178 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10179 if (!success)
10180 return false;
10181
10182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10183 return false;
10184
10185 //R[t2] = MemA[address+4,4];
10186
10187 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10188 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10189 if (!success)
10190 return false;
10191
10192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10193 return false;
10194
10195 //if wback then R[n] = offset_addr;
10196 if (wback)
10197 {
10198 context.type = eContextAdjustBaseRegister;
10199 context.SetAddress (offset_addr);
10200
10201 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10202 return false;
10203 }
10204 }
10205 return true;
10206 }
10207
10208 // A8.6.68 LDRD (register)
10209 // Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10210 // words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing.
10211 bool
EmulateLDRDRegister(const uint32_t opcode,const ARMEncoding encoding)10212 EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10213 {
10214 #if 0
10215 if ConditionPassed() then
10216 EncodingSpecificOperations();
10217 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10218 address = if index then offset_addr else R[n];
10219 R[t] = MemA[address,4];
10220 R[t2] = MemA[address+4,4];
10221 if wback then R[n] = offset_addr;
10222 #endif
10223
10224 bool success = false;
10225
10226 if (ConditionPassed(opcode))
10227 {
10228 uint32_t t;
10229 uint32_t t2;
10230 uint32_t n;
10231 uint32_t m;
10232 bool index;
10233 bool add;
10234 bool wback;
10235
10236 switch (encoding)
10237 {
10238 case eEncodingA1:
10239 // if Rt<0> == �1� then UNPREDICTABLE;
10240 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10241 t = Bits32 (opcode, 15, 12);
10242 if (BitIsSet (t, 0))
10243 return false;
10244 t2 = t + 1;
10245 n = Bits32 (opcode, 19, 16);
10246 m = Bits32 (opcode, 3, 0);
10247
10248 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10249 index = BitIsSet (opcode, 24);
10250 add = BitIsSet (opcode, 23);
10251 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10252
10253 // if P == �0� && W == �1� then UNPREDICTABLE;
10254 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10255 return false;
10256
10257 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10258 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10259 return false;
10260
10261 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10262 if (wback && ((n == 15) || (n == t) || (n == t2)))
10263 return false;
10264
10265 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10266 if ((ArchVersion() < 6) && wback && (m == n))
10267 return false;
10268 break;
10269
10270 default:
10271 return false;
10272 }
10273
10274 uint32_t Rn = ReadCoreReg (n, &success);
10275 if (!success)
10276 return false;
10277 RegisterInfo base_reg;
10278 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10279
10280 uint32_t Rm = ReadCoreReg (m, &success);
10281 if (!success)
10282 return false;
10283 RegisterInfo offset_reg;
10284 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10285
10286 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10287 addr_t offset_addr;
10288 if (add)
10289 offset_addr = Rn + Rm;
10290 else
10291 offset_addr = Rn - Rm;
10292
10293 // address = if index then offset_addr else R[n];
10294 addr_t address;
10295 if (index)
10296 address = offset_addr;
10297 else
10298 address = Rn;
10299
10300 EmulateInstruction::Context context;
10301 context.type = eContextRegisterLoad;
10302 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10303
10304 // R[t] = MemA[address,4];
10305 const uint32_t addr_byte_size = GetAddressByteSize();
10306 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10307 if (!success)
10308 return false;
10309
10310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10311 return false;
10312
10313 // R[t2] = MemA[address+4,4];
10314
10315 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10316 if (!success)
10317 return false;
10318
10319 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10320 return false;
10321
10322 // if wback then R[n] = offset_addr;
10323 if (wback)
10324 {
10325 context.type = eContextAdjustBaseRegister;
10326 context.SetAddress (offset_addr);
10327
10328 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10329 return false;
10330 }
10331 }
10332 return true;
10333 }
10334
10335 // A8.6.200 STRD (immediate)
10336 // Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10337 // stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing.
10338 bool
EmulateSTRDImm(const uint32_t opcode,const ARMEncoding encoding)10339 EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10340 {
10341 #if 0
10342 if ConditionPassed() then
10343 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10344 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10345 address = if index then offset_addr else R[n];
10346 MemA[address,4] = R[t];
10347 MemA[address+4,4] = R[t2];
10348 if wback then R[n] = offset_addr;
10349 #endif
10350
10351 bool success = false;
10352
10353 if (ConditionPassed(opcode))
10354 {
10355 uint32_t t;
10356 uint32_t t2;
10357 uint32_t n;
10358 uint32_t imm32;
10359 bool index;
10360 bool add;
10361 bool wback;
10362
10363 switch (encoding)
10364 {
10365 case eEncodingT1:
10366 // if P == �0� && W == �0� then SEE �Related encodings�;
10367 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10368 t = Bits32 (opcode, 15, 12);
10369 t2 = Bits32 (opcode, 11, 8);
10370 n = Bits32 (opcode, 19, 16);
10371 imm32 = Bits32 (opcode, 7, 0) << 2;
10372
10373 // index = (P == �1�); add = (U == �1�); wback = (W == �1�);
10374 index = BitIsSet (opcode, 24);
10375 add = BitIsSet (opcode, 23);
10376 wback = BitIsSet (opcode, 21);
10377
10378 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10379 if (wback && ((n == t) || (n == t2)))
10380 return false;
10381
10382 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10383 if ((n == 15) || BadReg (t) || BadReg (t2))
10384 return false;
10385
10386 break;
10387
10388 case eEncodingA1:
10389 // if Rt<0> == �1� then UNPREDICTABLE;
10390 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10391 t = Bits32 (opcode, 15, 12);
10392 if (BitIsSet (t, 0))
10393 return false;
10394
10395 t2 = t + 1;
10396 n = Bits32 (opcode, 19, 16);
10397 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10398
10399 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10400 index = BitIsSet (opcode, 24);
10401 add = BitIsSet (opcode, 23);
10402 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10403
10404 // if P == �0� && W == �1� then UNPREDICTABLE;
10405 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10406 return false;
10407
10408 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10409 if (wback && ((n == 15) || (n == t) || (n == t2)))
10410 return false;
10411
10412 // if t2 == 15 then UNPREDICTABLE;
10413 if (t2 == 15)
10414 return false;
10415
10416 break;
10417
10418 default:
10419 return false;
10420 }
10421
10422 RegisterInfo base_reg;
10423 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10424
10425 uint32_t Rn = ReadCoreReg (n, &success);
10426 if (!success)
10427 return false;
10428
10429 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10430 addr_t offset_addr;
10431 if (add)
10432 offset_addr = Rn + imm32;
10433 else
10434 offset_addr = Rn - imm32;
10435
10436 //address = if index then offset_addr else R[n];
10437 addr_t address;
10438 if (index)
10439 address = offset_addr;
10440 else
10441 address = Rn;
10442
10443 //MemA[address,4] = R[t];
10444 RegisterInfo data_reg;
10445 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10446
10447 uint32_t data = ReadCoreReg (t, &success);
10448 if (!success)
10449 return false;
10450
10451 EmulateInstruction::Context context;
10452 context.type = eContextRegisterStore;
10453 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10454
10455 const uint32_t addr_byte_size = GetAddressByteSize();
10456
10457 if (!MemAWrite (context, address, data, addr_byte_size))
10458 return false;
10459
10460 //MemA[address+4,4] = R[t2];
10461 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10462 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10463
10464 data = ReadCoreReg (t2, &success);
10465 if (!success)
10466 return false;
10467
10468 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10469 return false;
10470
10471 //if wback then R[n] = offset_addr;
10472 if (wback)
10473 {
10474 context.type = eContextAdjustBaseRegister;
10475 context.SetAddress (offset_addr);
10476
10477 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10478 return false;
10479 }
10480 }
10481 return true;
10482 }
10483
10484
10485 // A8.6.201 STRD (register)
10486 bool
EmulateSTRDReg(const uint32_t opcode,const ARMEncoding encoding)10487 EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10488 {
10489 #if 0
10490 if ConditionPassed() then
10491 EncodingSpecificOperations();
10492 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10493 address = if index then offset_addr else R[n];
10494 MemA[address,4] = R[t];
10495 MemA[address+4,4] = R[t2];
10496 if wback then R[n] = offset_addr;
10497 #endif
10498
10499 bool success = false;
10500
10501 if (ConditionPassed(opcode))
10502 {
10503 uint32_t t;
10504 uint32_t t2;
10505 uint32_t n;
10506 uint32_t m;
10507 bool index;
10508 bool add;
10509 bool wback;
10510
10511 switch (encoding)
10512 {
10513 case eEncodingA1:
10514 // if Rt<0> == �1� then UNPREDICTABLE;
10515 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10516 t = Bits32 (opcode, 15, 12);
10517 if (BitIsSet (t, 0))
10518 return false;
10519
10520 t2 = t+1;
10521 n = Bits32 (opcode, 19, 16);
10522 m = Bits32 (opcode, 3, 0);
10523
10524 // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
10525 index = BitIsSet (opcode, 24);
10526 add = BitIsSet (opcode, 23);
10527 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10528
10529 // if P == �0� && W == �1� then UNPREDICTABLE;
10530 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10531 return false;
10532
10533 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10534 if ((t2 == 15) || (m == 15))
10535 return false;
10536
10537 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10538 if (wback && ((n == 15) || (n == t) || (n == t2)))
10539 return false;
10540
10541 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10542 if ((ArchVersion() < 6) && wback && (m == n))
10543 return false;
10544
10545 break;
10546
10547 default:
10548 return false;
10549 }
10550
10551 RegisterInfo base_reg;
10552 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10553 RegisterInfo offset_reg;
10554 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10555 RegisterInfo data_reg;
10556
10557 uint32_t Rn = ReadCoreReg (n, &success);
10558 if (!success)
10559 return false;
10560
10561 uint32_t Rm = ReadCoreReg (m, &success);
10562 if (!success)
10563 return false;
10564
10565 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10566 addr_t offset_addr;
10567 if (add)
10568 offset_addr = Rn + Rm;
10569 else
10570 offset_addr = Rn - Rm;
10571
10572 // address = if index then offset_addr else R[n];
10573 addr_t address;
10574 if (index)
10575 address = offset_addr;
10576 else
10577 address = Rn;
10578 // MemA[address,4] = R[t];
10579 uint32_t Rt = ReadCoreReg (t, &success);
10580 if (!success)
10581 return false;
10582
10583 EmulateInstruction::Context context;
10584 context.type = eContextRegisterStore;
10585 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
10586 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10587
10588 const uint32_t addr_byte_size = GetAddressByteSize();
10589
10590 if (!MemAWrite (context, address, Rt, addr_byte_size))
10591 return false;
10592
10593 // MemA[address+4,4] = R[t2];
10594 uint32_t Rt2 = ReadCoreReg (t2, &success);
10595 if (!success)
10596 return false;
10597
10598 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
10599
10600 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10601
10602 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10603 return false;
10604
10605 // if wback then R[n] = offset_addr;
10606 if (wback)
10607 {
10608 context.type = eContextAdjustBaseRegister;
10609 context.SetAddress (offset_addr);
10610
10611 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10612 return false;
10613
10614 }
10615 }
10616 return true;
10617 }
10618
10619 // A8.6.319 VLDM
10620 // Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10621 // an ARM core register.
10622 bool
EmulateVLDM(const uint32_t opcode,const ARMEncoding encoding)10623 EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10624 {
10625 #if 0
10626 if ConditionPassed() then
10627 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10628 address = if add then R[n] else R[n]-imm32;
10629 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10630 for r = 0 to regs-1
10631 if single_regs then
10632 S[d+r] = MemA[address,4]; address = address+4;
10633 else
10634 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10635 // Combine the word-aligned words in the correct order for current endianness.
10636 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10637 #endif
10638
10639 bool success = false;
10640
10641 if (ConditionPassed(opcode))
10642 {
10643 bool single_regs;
10644 bool add;
10645 bool wback;
10646 uint32_t d;
10647 uint32_t n;
10648 uint32_t imm32;
10649 uint32_t regs;
10650
10651 switch (encoding)
10652 {
10653 case eEncodingT1:
10654 case eEncodingA1:
10655 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10656 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
10657 // if P == �1� && W == �0� then SEE VLDR;
10658 // if P == U && W == �1� then UNDEFINED;
10659 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10660 return false;
10661
10662 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10663 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
10664 single_regs = false;
10665 add = BitIsSet (opcode, 23);
10666 wback = BitIsSet (opcode, 21);
10667
10668 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10669 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10670 n = Bits32 (opcode, 19, 16);
10671 imm32 = Bits32 (opcode, 7, 0) << 2;
10672
10673 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FLDMX�.
10674 regs = Bits32 (opcode, 7, 0) / 2;
10675
10676 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10677 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10678 return false;
10679
10680 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10681 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10682 return false;
10683
10684 break;
10685
10686 case eEncodingT2:
10687 case eEncodingA2:
10688 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10689 // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
10690 // if P == �1� && W == �0� then SEE VLDR;
10691 // if P == U && W == �1� then UNDEFINED;
10692 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10693 return false;
10694
10695 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10696 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
10697 single_regs = true;
10698 add = BitIsSet (opcode, 23);
10699 wback = BitIsSet (opcode, 21);
10700 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10701 n = Bits32 (opcode, 19, 16);
10702
10703 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
10704 imm32 = Bits32 (opcode, 7, 0) << 2;
10705 regs = Bits32 (opcode, 7, 0);
10706
10707 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10708 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10709 return false;
10710
10711 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10712 if ((regs == 0) || ((d + regs) > 32))
10713 return false;
10714 break;
10715
10716 default:
10717 return false;
10718 }
10719
10720 RegisterInfo base_reg;
10721 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10722
10723 uint32_t Rn = ReadCoreReg (n, &success);
10724 if (!success)
10725 return false;
10726
10727 // address = if add then R[n] else R[n]-imm32;
10728 addr_t address;
10729 if (add)
10730 address = Rn;
10731 else
10732 address = Rn - imm32;
10733
10734 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10735 EmulateInstruction::Context context;
10736
10737 if (wback)
10738 {
10739 uint32_t value;
10740 if (add)
10741 value = Rn + imm32;
10742 else
10743 value = Rn - imm32;
10744
10745 context.type = eContextAdjustBaseRegister;
10746 context.SetImmediateSigned (value - Rn);
10747 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10748 return false;
10749
10750 }
10751
10752 const uint32_t addr_byte_size = GetAddressByteSize();
10753 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10754
10755 context.type = eContextRegisterLoad;
10756
10757 // for r = 0 to regs-1
10758 for (uint32_t r = 0; r < regs; ++r)
10759 {
10760 if (single_regs)
10761 {
10762 // S[d+r] = MemA[address,4]; address = address+4;
10763 context.SetRegisterPlusOffset (base_reg, address - Rn);
10764
10765 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10766 if (!success)
10767 return false;
10768
10769 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10770 return false;
10771
10772 address = address + 4;
10773 }
10774 else
10775 {
10776 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10777 context.SetRegisterPlusOffset (base_reg, address - Rn);
10778 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10779 if (!success)
10780 return false;
10781
10782 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10783 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10784 if (!success)
10785 return false;
10786
10787 address = address + 8;
10788 // // Combine the word-aligned words in the correct order for current endianness.
10789 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10790 uint64_t data;
10791 if (GetByteOrder() == eByteOrderBig)
10792 {
10793 data = word1;
10794 data = (data << 32) | word2;
10795 }
10796 else
10797 {
10798 data = word2;
10799 data = (data << 32) | word1;
10800 }
10801
10802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10803 return false;
10804 }
10805 }
10806 }
10807 return true;
10808 }
10809
10810 // A8.6.399 VSTM
10811 // Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10812 // ARM core register.
10813 bool
EmulateVSTM(const uint32_t opcode,const ARMEncoding encoding)10814 EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10815 {
10816 #if 0
10817 if ConditionPassed() then
10818 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10819 address = if add then R[n] else R[n]-imm32;
10820 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10821 for r = 0 to regs-1
10822 if single_regs then
10823 MemA[address,4] = S[d+r]; address = address+4;
10824 else
10825 // Store as two word-aligned words in the correct order for current endianness.
10826 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10827 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10828 address = address+8;
10829 #endif
10830
10831 bool success = false;
10832
10833 if (ConditionPassed (opcode))
10834 {
10835 bool single_regs;
10836 bool add;
10837 bool wback;
10838 uint32_t d;
10839 uint32_t n;
10840 uint32_t imm32;
10841 uint32_t regs;
10842
10843 switch (encoding)
10844 {
10845 case eEncodingT1:
10846 case eEncodingA1:
10847 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10848 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
10849 // if P == �1� && W == �0� then SEE VSTR;
10850 // if P == U && W == �1� then UNDEFINED;
10851 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10852 return false;
10853
10854 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10855 // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
10856 single_regs = false;
10857 add = BitIsSet (opcode, 23);
10858 wback = BitIsSet (opcode, 21);
10859
10860 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
10861 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10862 n = Bits32 (opcode, 19, 16);
10863 imm32 = Bits32 (opcode, 7, 0) << 2;
10864
10865 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FSTMX�.
10866 regs = Bits32 (opcode, 7, 0) / 2;
10867
10868 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10869 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10870 return false;
10871
10872 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10873 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10874 return false;
10875
10876 break;
10877
10878 case eEncodingT2:
10879 case eEncodingA2:
10880 // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
10881 // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
10882 // if P == �1� && W == �0� then SEE VSTR;
10883 // if P == U && W == �1� then UNDEFINED;
10884 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10885 return false;
10886
10887 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10888 // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
10889 single_regs = true;
10890 add = BitIsSet (opcode, 23);
10891 wback = BitIsSet (opcode, 21);
10892 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10893 n = Bits32 (opcode, 19, 16);
10894
10895 // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
10896 imm32 = Bits32 (opcode, 7, 0) << 2;
10897 regs = Bits32 (opcode, 7, 0);
10898
10899 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10900 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10901 return false;
10902
10903 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10904 if ((regs == 0) || ((d + regs) > 32))
10905 return false;
10906
10907 break;
10908
10909 default:
10910 return false;
10911 }
10912
10913 RegisterInfo base_reg;
10914 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10915
10916 uint32_t Rn = ReadCoreReg (n, &success);
10917 if (!success)
10918 return false;
10919
10920 // address = if add then R[n] else R[n]-imm32;
10921 addr_t address;
10922 if (add)
10923 address = Rn;
10924 else
10925 address = Rn - imm32;
10926
10927 EmulateInstruction::Context context;
10928 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
10929 if (wback)
10930 {
10931 uint32_t value;
10932 if (add)
10933 value = Rn + imm32;
10934 else
10935 value = Rn - imm32;
10936
10937 context.type = eContextAdjustBaseRegister;
10938 context.SetRegisterPlusOffset (base_reg, value - Rn);
10939
10940 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10941 return false;
10942 }
10943
10944 const uint32_t addr_byte_size = GetAddressByteSize();
10945 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10946
10947 context.type = eContextRegisterStore;
10948 // for r = 0 to regs-1
10949 for (uint32_t r = 0; r < regs; ++r)
10950 {
10951
10952 if (single_regs)
10953 {
10954 // MemA[address,4] = S[d+r]; address = address+4;
10955 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10956 if (!success)
10957 return false;
10958
10959 RegisterInfo data_reg;
10960 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
10961 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10962 if (!MemAWrite (context, address, data, addr_byte_size))
10963 return false;
10964
10965 address = address + 4;
10966 }
10967 else
10968 {
10969 // // Store as two word-aligned words in the correct order for current endianness.
10970 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10971 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10972 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10973 if (!success)
10974 return false;
10975
10976 RegisterInfo data_reg;
10977 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
10978
10979 if (GetByteOrder() == eByteOrderBig)
10980 {
10981 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10982 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10983 return false;
10984
10985 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10986 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10987 return false;
10988 }
10989 else
10990 {
10991 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10992 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10993 return false;
10994
10995 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10996 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10997 return false;
10998 }
10999 // address = address+8;
11000 address = address + 8;
11001 }
11002 }
11003 }
11004 return true;
11005 }
11006
11007 // A8.6.320
11008 // This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
11009 // an optional offset.
11010 bool
EmulateVLDR(const uint32_t opcode,ARMEncoding encoding)11011 EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
11012 {
11013 #if 0
11014 if ConditionPassed() then
11015 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11016 base = if n == 15 then Align(PC,4) else R[n];
11017 address = if add then (base + imm32) else (base - imm32);
11018 if single_reg then
11019 S[d] = MemA[address,4];
11020 else
11021 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11022 // Combine the word-aligned words in the correct order for current endianness.
11023 D[d] = if BigEndian() then word1:word2 else word2:word1;
11024 #endif
11025
11026 bool success = false;
11027
11028 if (ConditionPassed (opcode))
11029 {
11030 bool single_reg;
11031 bool add;
11032 uint32_t imm32;
11033 uint32_t d;
11034 uint32_t n;
11035
11036 switch (encoding)
11037 {
11038 case eEncodingT1:
11039 case eEncodingA1:
11040 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11041 single_reg = false;
11042 add = BitIsSet (opcode, 23);
11043 imm32 = Bits32 (opcode, 7, 0) << 2;
11044
11045 // d = UInt(D:Vd); n = UInt(Rn);
11046 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11047 n = Bits32 (opcode, 19, 16);
11048
11049 break;
11050
11051 case eEncodingT2:
11052 case eEncodingA2:
11053 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11054 single_reg = true;
11055 add = BitIsSet (opcode, 23);
11056 imm32 = Bits32 (opcode, 7, 0) << 2;
11057
11058 // d = UInt(Vd:D); n = UInt(Rn);
11059 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11060 n = Bits32 (opcode, 19, 16);
11061
11062 break;
11063
11064 default:
11065 return false;
11066 }
11067 RegisterInfo base_reg;
11068 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11069
11070 uint32_t Rn = ReadCoreReg (n, &success);
11071 if (!success)
11072 return false;
11073
11074 // base = if n == 15 then Align(PC,4) else R[n];
11075 uint32_t base;
11076 if (n == 15)
11077 base = AlignPC (Rn);
11078 else
11079 base = Rn;
11080
11081 // address = if add then (base + imm32) else (base - imm32);
11082 addr_t address;
11083 if (add)
11084 address = base + imm32;
11085 else
11086 address = base - imm32;
11087
11088 const uint32_t addr_byte_size = GetAddressByteSize();
11089 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11090
11091 EmulateInstruction::Context context;
11092 context.type = eContextRegisterLoad;
11093 context.SetRegisterPlusOffset (base_reg, address - base);
11094
11095 if (single_reg)
11096 {
11097 // S[d] = MemA[address,4];
11098 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11099 if (!success)
11100 return false;
11101
11102 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11103 return false;
11104 }
11105 else
11106 {
11107 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11108 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11109 if (!success)
11110 return false;
11111
11112 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11113 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11114 if (!success)
11115 return false;
11116 // // Combine the word-aligned words in the correct order for current endianness.
11117 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11118 uint64_t data64;
11119 if (GetByteOrder() == eByteOrderBig)
11120 {
11121 data64 = word1;
11122 data64 = (data64 << 32) | word2;
11123 }
11124 else
11125 {
11126 data64 = word2;
11127 data64 = (data64 << 32) | word1;
11128 }
11129
11130 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11131 return false;
11132 }
11133 }
11134 return true;
11135 }
11136
11137 // A8.6.400 VSTR
11138 // This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11139 // optional offset.
11140 bool
EmulateVSTR(const uint32_t opcode,ARMEncoding encoding)11141 EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11142 {
11143 #if 0
11144 if ConditionPassed() then
11145 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11146 address = if add then (R[n] + imm32) else (R[n] - imm32);
11147 if single_reg then
11148 MemA[address,4] = S[d];
11149 else
11150 // Store as two word-aligned words in the correct order for current endianness.
11151 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11152 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11153 #endif
11154
11155 bool success = false;
11156
11157 if (ConditionPassed (opcode))
11158 {
11159 bool single_reg;
11160 bool add;
11161 uint32_t imm32;
11162 uint32_t d;
11163 uint32_t n;
11164
11165 switch (encoding)
11166 {
11167 case eEncodingT1:
11168 case eEncodingA1:
11169 // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11170 single_reg = false;
11171 add = BitIsSet (opcode, 23);
11172 imm32 = Bits32 (opcode, 7, 0) << 2;
11173
11174 // d = UInt(D:Vd); n = UInt(Rn);
11175 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11176 n = Bits32 (opcode, 19, 16);
11177
11178 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11179 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11180 return false;
11181
11182 break;
11183
11184 case eEncodingT2:
11185 case eEncodingA2:
11186 // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
11187 single_reg = true;
11188 add = BitIsSet (opcode, 23);
11189 imm32 = Bits32 (opcode, 7, 0) << 2;
11190
11191 // d = UInt(Vd:D); n = UInt(Rn);
11192 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11193 n = Bits32 (opcode, 19, 16);
11194
11195 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11196 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11197 return false;
11198
11199 break;
11200
11201 default:
11202 return false;
11203 }
11204
11205 RegisterInfo base_reg;
11206 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11207
11208 uint32_t Rn = ReadCoreReg (n, &success);
11209 if (!success)
11210 return false;
11211
11212 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11213 addr_t address;
11214 if (add)
11215 address = Rn + imm32;
11216 else
11217 address = Rn - imm32;
11218
11219 const uint32_t addr_byte_size = GetAddressByteSize();
11220 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11221
11222 RegisterInfo data_reg;
11223 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
11224 EmulateInstruction::Context context;
11225 context.type = eContextRegisterStore;
11226 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11227
11228 if (single_reg)
11229 {
11230 // MemA[address,4] = S[d];
11231 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11232 if (!success)
11233 return false;
11234
11235 if (!MemAWrite (context, address, data, addr_byte_size))
11236 return false;
11237 }
11238 else
11239 {
11240 // // Store as two word-aligned words in the correct order for current endianness.
11241 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11242 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11243 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11244 if (!success)
11245 return false;
11246
11247 if (GetByteOrder() == eByteOrderBig)
11248 {
11249 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11250 return false;
11251
11252 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11253 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11254 return false;
11255 }
11256 else
11257 {
11258 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11259 return false;
11260
11261 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11262 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11263 return false;
11264 }
11265 }
11266 }
11267 return true;
11268 }
11269
11270 // A8.6.307 VLDI1 (multiple single elements)
11271 // This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11272 // element of each register is loaded.
11273 bool
EmulateVLD1Multiple(const uint32_t opcode,ARMEncoding encoding)11274 EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11275 {
11276 #if 0
11277 if ConditionPassed() then
11278 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11279 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11280 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11281 for r = 0 to regs-1
11282 for e = 0 to elements-1
11283 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11284 address = address + ebytes;
11285 #endif
11286
11287 bool success = false;
11288
11289 if (ConditionPassed (opcode))
11290 {
11291 uint32_t regs;
11292 uint32_t alignment;
11293 uint32_t ebytes;
11294 uint32_t esize;
11295 uint32_t elements;
11296 uint32_t d;
11297 uint32_t n;
11298 uint32_t m;
11299 bool wback;
11300 bool register_index;
11301
11302 switch (encoding)
11303 {
11304 case eEncodingT1:
11305 case eEncodingA1:
11306 {
11307 // case type of
11308 // when �0111�
11309 // regs = 1; if align<1> == �1� then UNDEFINED;
11310 // when �1010�
11311 // regs = 2; if align == �11� then UNDEFINED;
11312 // when �0110�
11313 // regs = 3; if align<1> == �1� then UNDEFINED;
11314 // when �0010�
11315 // regs = 4;
11316 // otherwise
11317 // SEE �Related encodings�;
11318 uint32_t type = Bits32 (opcode, 11, 8);
11319 uint32_t align = Bits32 (opcode, 5, 4);
11320 if (type == 7) // '0111'
11321 {
11322 regs = 1;
11323 if (BitIsSet (align, 1))
11324 return false;
11325 }
11326 else if (type == 10) // '1010'
11327 {
11328 regs = 2;
11329 if (align == 3)
11330 return false;
11331
11332 }
11333 else if (type == 6) // '0110'
11334 {
11335 regs = 3;
11336 if (BitIsSet (align, 1))
11337 return false;
11338 }
11339 else if (type == 2) // '0010'
11340 {
11341 regs = 4;
11342 }
11343 else
11344 return false;
11345
11346 // alignment = if align == �00� then 1 else 4 << UInt(align);
11347 if (align == 0)
11348 alignment = 1;
11349 else
11350 alignment = 4 << align;
11351
11352 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11353 ebytes = 1 << Bits32 (opcode, 7, 6);
11354 esize = 8 * ebytes;
11355 elements = 8 / ebytes;
11356
11357 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11358 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11359 n = Bits32 (opcode, 19, 15);
11360 m = Bits32 (opcode, 3, 0);
11361
11362 // wback = (m != 15); register_index = (m != 15 && m != 13);
11363 wback = (m != 15);
11364 register_index = ((m != 15) && (m != 13));
11365
11366 // if d+regs > 32 then UNPREDICTABLE;
11367 if ((d + regs) > 32)
11368 return false;
11369 }
11370 break;
11371
11372 default:
11373 return false;
11374 }
11375
11376 RegisterInfo base_reg;
11377 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11378
11379 uint32_t Rn = ReadCoreReg (n, &success);
11380 if (!success)
11381 return false;
11382
11383 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11384 addr_t address = Rn;
11385 if ((address % alignment) != 0)
11386 return false;
11387
11388 EmulateInstruction::Context context;
11389 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11390 if (wback)
11391 {
11392 uint32_t Rm = ReadCoreReg (m, &success);
11393 if (!success)
11394 return false;
11395
11396 uint32_t offset;
11397 if (register_index)
11398 offset = Rm;
11399 else
11400 offset = 8 * regs;
11401
11402 uint32_t value = Rn + offset;
11403 context.type = eContextAdjustBaseRegister;
11404 context.SetRegisterPlusOffset (base_reg, offset);
11405
11406 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11407 return false;
11408
11409 }
11410
11411 // for r = 0 to regs-1
11412 for (uint32_t r = 0; r < regs; ++r)
11413 {
11414 // for e = 0 to elements-1
11415 uint64_t assembled_data = 0;
11416 for (uint32_t e = 0; e < elements; ++e)
11417 {
11418 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11419 context.type = eContextRegisterLoad;
11420 context.SetRegisterPlusOffset (base_reg, address - Rn);
11421 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11422 if (!success)
11423 return false;
11424
11425 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11426
11427 // address = address + ebytes;
11428 address = address + ebytes;
11429 }
11430 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11431 return false;
11432 }
11433 }
11434 return true;
11435 }
11436
11437 // A8.6.308 VLD1 (single element to one lane)
11438 //
11439 bool
EmulateVLD1Single(const uint32_t opcode,const ARMEncoding encoding)11440 EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11441 {
11442 #if 0
11443 if ConditionPassed() then
11444 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11445 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11446 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11447 Elem[D[d],index,esize] = MemU[address,ebytes];
11448 #endif
11449
11450 bool success = false;
11451
11452 if (ConditionPassed (opcode))
11453 {
11454 uint32_t ebytes;
11455 uint32_t esize;
11456 uint32_t index;
11457 uint32_t alignment;
11458 uint32_t d;
11459 uint32_t n;
11460 uint32_t m;
11461 bool wback;
11462 bool register_index;
11463
11464 switch (encoding)
11465 {
11466 case eEncodingT1:
11467 case eEncodingA1:
11468 {
11469 uint32_t size = Bits32 (opcode, 11, 10);
11470 uint32_t index_align = Bits32 (opcode, 7, 4);
11471 // if size == �11� then SEE VLD1 (single element to all lanes);
11472 if (size == 3)
11473 return EmulateVLD1SingleAll (opcode, encoding);
11474 // case size of
11475 if (size == 0) // when '00'
11476 {
11477 // if index_align<0> != �0� then UNDEFINED;
11478 if (BitIsClear (index_align, 0))
11479 return false;
11480
11481 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11482 ebytes = 1;
11483 esize = 8;
11484 index = Bits32 (index_align, 3, 1);
11485 alignment = 1;
11486 }
11487 else if (size == 1) // when �01�
11488 {
11489 // if index_align<1> != �0� then UNDEFINED;
11490 if (BitIsClear (index_align, 1))
11491 return false;
11492
11493 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11494 ebytes = 2;
11495 esize = 16;
11496 index = Bits32 (index_align, 3, 2);
11497
11498 // alignment = if index_align<0> == �0� then 1 else 2;
11499 if (BitIsClear (index_align, 0))
11500 alignment = 1;
11501 else
11502 alignment = 2;
11503 }
11504 else if (size == 2) // when �10�
11505 {
11506 // if index_align<2> != �0� then UNDEFINED;
11507 if (BitIsClear (index_align, 2))
11508 return false;
11509
11510 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
11511 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11512 return false;
11513
11514 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11515 ebytes = 4;
11516 esize = 32;
11517 index = Bit32 (index_align, 3);
11518
11519 // alignment = if index_align<1:0> == �00� then 1 else 4;
11520 if (Bits32 (index_align, 1, 0) == 0)
11521 alignment = 1;
11522 else
11523 alignment = 4;
11524 }
11525 else
11526 {
11527 return false;
11528 }
11529 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11530 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11531 n = Bits32 (opcode, 19, 16);
11532 m = Bits32 (opcode, 3, 0);
11533
11534 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11535 wback = (m != 15);
11536 register_index = ((m != 15) && (m != 13));
11537
11538 if (n == 15)
11539 return false;
11540
11541 }
11542 break;
11543
11544 default:
11545 return false;
11546 }
11547
11548 RegisterInfo base_reg;
11549 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11550
11551 uint32_t Rn = ReadCoreReg (n, &success);
11552 if (!success)
11553 return false;
11554
11555 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11556 addr_t address = Rn;
11557 if ((address % alignment) != 0)
11558 return false;
11559
11560 EmulateInstruction::Context context;
11561 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11562 if (wback)
11563 {
11564 uint32_t Rm = ReadCoreReg (m, &success);
11565 if (!success)
11566 return false;
11567
11568 uint32_t offset;
11569 if (register_index)
11570 offset = Rm;
11571 else
11572 offset = ebytes;
11573
11574 uint32_t value = Rn + offset;
11575
11576 context.type = eContextAdjustBaseRegister;
11577 context.SetRegisterPlusOffset (base_reg, offset);
11578
11579 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11580 return false;
11581 }
11582
11583 // Elem[D[d],index,esize] = MemU[address,ebytes];
11584 uint32_t element = MemURead (context, address, esize, 0, &success);
11585 if (!success)
11586 return false;
11587
11588 element = element << (index * esize);
11589
11590 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11591 if (!success)
11592 return false;
11593
11594 uint64_t all_ones = -1;
11595 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11596 // at element & to the right of element.
11597 if (index > 0)
11598 mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes.
11599 // now mask should be 0's where element goes & 1's
11600 // everywhere else.
11601
11602 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11603 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11604
11605 context.type = eContextRegisterLoad;
11606 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11607 return false;
11608 }
11609 return true;
11610 }
11611
11612 // A8.6.391 VST1 (multiple single elements)
11613 // Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11614 // interleaving. Every element of each register is stored.
11615 bool
EmulateVST1Multiple(const uint32_t opcode,ARMEncoding encoding)11616 EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11617 {
11618 #if 0
11619 if ConditionPassed() then
11620 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11621 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11622 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11623 for r = 0 to regs-1
11624 for e = 0 to elements-1
11625 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11626 address = address + ebytes;
11627 #endif
11628
11629 bool success = false;
11630
11631 if (ConditionPassed (opcode))
11632 {
11633 uint32_t regs;
11634 uint32_t alignment;
11635 uint32_t ebytes;
11636 uint32_t esize;
11637 uint32_t elements;
11638 uint32_t d;
11639 uint32_t n;
11640 uint32_t m;
11641 bool wback;
11642 bool register_index;
11643
11644 switch (encoding)
11645 {
11646 case eEncodingT1:
11647 case eEncodingA1:
11648 {
11649 uint32_t type = Bits32 (opcode, 11, 8);
11650 uint32_t align = Bits32 (opcode, 5, 4);
11651
11652 // case type of
11653 if (type == 7) // when �0111�
11654 {
11655 // regs = 1; if align<1> == �1� then UNDEFINED;
11656 regs = 1;
11657 if (BitIsSet (align, 1))
11658 return false;
11659 }
11660 else if (type == 10) // when �1010�
11661 {
11662 // regs = 2; if align == �11� then UNDEFINED;
11663 regs = 2;
11664 if (align == 3)
11665 return false;
11666 }
11667 else if (type == 6) // when �0110�
11668 {
11669 // regs = 3; if align<1> == �1� then UNDEFINED;
11670 regs = 3;
11671 if (BitIsSet (align, 1))
11672 return false;
11673 }
11674 else if (type == 2) // when �0010�
11675 // regs = 4;
11676 regs = 4;
11677 else // otherwise
11678 // SEE �Related encodings�;
11679 return false;
11680
11681 // alignment = if align == �00� then 1 else 4 << UInt(align);
11682 if (align == 0)
11683 alignment = 1;
11684 else
11685 alignment = 4 << align;
11686
11687 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11688 ebytes = 1 << Bits32 (opcode,7, 6);
11689 esize = 8 * ebytes;
11690 elements = 8 / ebytes;
11691
11692 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11693 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11694 n = Bits32 (opcode, 19, 16);
11695 m = Bits32 (opcode, 3, 0);
11696
11697 // wback = (m != 15); register_index = (m != 15 && m != 13);
11698 wback = (m != 15);
11699 register_index = ((m != 15) && (m != 13));
11700
11701 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11702 if ((d + regs) > 32)
11703 return false;
11704
11705 if (n == 15)
11706 return false;
11707
11708 }
11709 break;
11710
11711 default:
11712 return false;
11713 }
11714
11715 RegisterInfo base_reg;
11716 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11717
11718 uint32_t Rn = ReadCoreReg (n, &success);
11719 if (!success)
11720 return false;
11721
11722 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11723 addr_t address = Rn;
11724 if ((address % alignment) != 0)
11725 return false;
11726
11727 EmulateInstruction::Context context;
11728 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11729 if (wback)
11730 {
11731 uint32_t Rm = ReadCoreReg (m, &success);
11732 if (!success)
11733 return false;
11734
11735 uint32_t offset;
11736 if (register_index)
11737 offset = Rm;
11738 else
11739 offset = 8 * regs;
11740
11741 context.type = eContextAdjustBaseRegister;
11742 context.SetRegisterPlusOffset (base_reg, offset);
11743
11744 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11745 return false;
11746 }
11747
11748 RegisterInfo data_reg;
11749 context.type = eContextRegisterStore;
11750 // for r = 0 to regs-1
11751 for (uint32_t r = 0; r < regs; ++r)
11752 {
11753 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
11754 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11755 if (!success)
11756 return false;
11757
11758 // for e = 0 to elements-1
11759 for (uint32_t e = 0; e < elements; ++e)
11760 {
11761 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
11762 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
11763
11764 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11765 if (!MemUWrite (context, address, word, ebytes))
11766 return false;
11767
11768 // address = address + ebytes;
11769 address = address + ebytes;
11770 }
11771 }
11772 }
11773 return true;
11774 }
11775
11776 // A8.6.392 VST1 (single element from one lane)
11777 // This instruction stores one element to memory from one element of a register.
11778 bool
EmulateVST1Single(const uint32_t opcode,ARMEncoding encoding)11779 EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11780 {
11781 #if 0
11782 if ConditionPassed() then
11783 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11784 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11785 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11786 MemU[address,ebytes] = Elem[D[d],index,esize];
11787 #endif
11788
11789 bool success = false;
11790
11791 if (ConditionPassed (opcode))
11792 {
11793 uint32_t ebytes;
11794 uint32_t esize;
11795 uint32_t index;
11796 uint32_t alignment;
11797 uint32_t d;
11798 uint32_t n;
11799 uint32_t m;
11800 bool wback;
11801 bool register_index;
11802
11803 switch (encoding)
11804 {
11805 case eEncodingT1:
11806 case eEncodingA1:
11807 {
11808 uint32_t size = Bits32 (opcode, 11, 10);
11809 uint32_t index_align = Bits32 (opcode, 7, 4);
11810
11811 // if size == �11� then UNDEFINED;
11812 if (size == 3)
11813 return false;
11814
11815 // case size of
11816 if (size == 0) // when �00�
11817 {
11818 // if index_align<0> != �0� then UNDEFINED;
11819 if (BitIsClear (index_align, 0))
11820 return false;
11821 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11822 ebytes = 1;
11823 esize = 8;
11824 index = Bits32 (index_align, 3, 1);
11825 alignment = 1;
11826 }
11827 else if (size == 1) // when �01�
11828 {
11829 // if index_align<1> != �0� then UNDEFINED;
11830 if (BitIsClear (index_align, 1))
11831 return false;
11832
11833 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11834 ebytes = 2;
11835 esize = 16;
11836 index = Bits32 (index_align, 3, 2);
11837
11838 // alignment = if index_align<0> == �0� then 1 else 2;
11839 if (BitIsClear (index_align, 0))
11840 alignment = 1;
11841 else
11842 alignment = 2;
11843 }
11844 else if (size == 2) // when �10�
11845 {
11846 // if index_align<2> != �0� then UNDEFINED;
11847 if (BitIsClear (index_align, 2))
11848 return false;
11849
11850 // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
11851 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11852 return false;
11853
11854 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11855 ebytes = 4;
11856 esize = 32;
11857 index = Bit32 (index_align, 3);
11858
11859 // alignment = if index_align<1:0> == �00� then 1 else 4;
11860 if (Bits32 (index_align, 1, 0) == 0)
11861 alignment = 1;
11862 else
11863 alignment = 4;
11864 }
11865 else
11866 {
11867 return false;
11868 }
11869 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11870 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11871 n = Bits32 (opcode, 19, 16);
11872 m = Bits32 (opcode, 3, 0);
11873
11874 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11875 wback = (m != 15);
11876 register_index = ((m != 15) && (m != 13));
11877
11878 if (n == 15)
11879 return false;
11880 }
11881 break;
11882
11883 default:
11884 return false;
11885 }
11886
11887 RegisterInfo base_reg;
11888 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
11889
11890 uint32_t Rn = ReadCoreReg (n, &success);
11891 if (!success)
11892 return false;
11893
11894 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11895 addr_t address = Rn;
11896 if ((address % alignment) != 0)
11897 return false;
11898
11899 EmulateInstruction::Context context;
11900 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11901 if (wback)
11902 {
11903 uint32_t Rm = ReadCoreReg (m, &success);
11904 if (!success)
11905 return false;
11906
11907 uint32_t offset;
11908 if (register_index)
11909 offset = Rm;
11910 else
11911 offset = ebytes;
11912
11913 context.type = eContextAdjustBaseRegister;
11914 context.SetRegisterPlusOffset (base_reg, offset);
11915
11916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11917 return false;
11918 }
11919
11920 // MemU[address,ebytes] = Elem[D[d],index,esize];
11921 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11922 if (!success)
11923 return false;
11924
11925 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11926
11927 RegisterInfo data_reg;
11928 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
11929 context.type = eContextRegisterStore;
11930 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11931
11932 if (!MemUWrite (context, address, word, ebytes))
11933 return false;
11934 }
11935 return true;
11936 }
11937
11938 // A8.6.309 VLD1 (single element to all lanes)
11939 // This instruction loads one element from memory into every element of one or two vectors.
11940 bool
EmulateVLD1SingleAll(const uint32_t opcode,const ARMEncoding encoding)11941 EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
11942 {
11943 #if 0
11944 if ConditionPassed() then
11945 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11946 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11947 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11948 replicated_element = Replicate(MemU[address,ebytes], elements);
11949 for r = 0 to regs-1
11950 D[d+r] = replicated_element;
11951 #endif
11952
11953 bool success = false;
11954
11955 if (ConditionPassed (opcode))
11956 {
11957 uint32_t ebytes;
11958 uint32_t elements;
11959 uint32_t regs;
11960 uint32_t alignment;
11961 uint32_t d;
11962 uint32_t n;
11963 uint32_t m;
11964 bool wback;
11965 bool register_index;
11966
11967 switch (encoding)
11968 {
11969 case eEncodingT1:
11970 case eEncodingA1:
11971 {
11972 //if size == �11� || (size == �00� && a == �1�) then UNDEFINED;
11973 uint32_t size = Bits32 (opcode, 7, 6);
11974 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11975 return false;
11976
11977 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == �0� then 1 else 2;
11978 ebytes = 1 << size;
11979 elements = 8 / ebytes;
11980 if (BitIsClear (opcode, 5))
11981 regs = 1;
11982 else
11983 regs = 2;
11984
11985 //alignment = if a == �0� then 1 else ebytes;
11986 if (BitIsClear (opcode, 4))
11987 alignment = 1;
11988 else
11989 alignment = ebytes;
11990
11991 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11992 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11993 n = Bits32 (opcode, 19, 16);
11994 m = Bits32 (opcode, 3, 0);
11995
11996 //wback = (m != 15); register_index = (m != 15 && m != 13);
11997 wback = (m != 15);
11998 register_index = ((m != 15) && (m != 13));
11999
12000 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12001 if ((d + regs) > 32)
12002 return false;
12003
12004 if (n == 15)
12005 return false;
12006 }
12007 break;
12008
12009 default:
12010 return false;
12011 }
12012
12013 RegisterInfo base_reg;
12014 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
12015
12016 uint32_t Rn = ReadCoreReg (n, &success);
12017 if (!success)
12018 return false;
12019
12020 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12021 addr_t address = Rn;
12022 if ((address % alignment) != 0)
12023 return false;
12024
12025 EmulateInstruction::Context context;
12026 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12027 if (wback)
12028 {
12029 uint32_t Rm = ReadCoreReg (m, &success);
12030 if (!success)
12031 return false;
12032
12033 uint32_t offset;
12034 if (register_index)
12035 offset = Rm;
12036 else
12037 offset = ebytes;
12038
12039 context.type = eContextAdjustBaseRegister;
12040 context.SetRegisterPlusOffset (base_reg, offset);
12041
12042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
12043 return false;
12044 }
12045
12046 // replicated_element = Replicate(MemU[address,ebytes], elements);
12047
12048 context.type = eContextRegisterLoad;
12049 uint64_t word = MemURead (context, address, ebytes, 0, &success);
12050 if (!success)
12051 return false;
12052
12053 uint64_t replicated_element = 0;
12054 uint32_t esize = ebytes * 8;
12055 for (uint32_t e = 0; e < elements; ++e)
12056 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
12057
12058 // for r = 0 to regs-1
12059 for (uint32_t r = 0; r < regs; ++r)
12060 {
12061 // D[d+r] = replicated_element;
12062 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
12063 return false;
12064 }
12065 }
12066 return true;
12067 }
12068
12069 // B6.2.13 SUBS PC, LR and related instructions
12070 //The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
12071 // immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12072 bool
EmulateSUBSPcLrEtc(const uint32_t opcode,const ARMEncoding encoding)12073 EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12074 {
12075 #if 0
12076 if ConditionPassed() then
12077 EncodingSpecificOperations();
12078 if CurrentInstrSet() == InstrSet_ThumbEE then
12079 UNPREDICTABLE;
12080 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12081 case opcode of
12082 when �0000� result = R[n] AND operand2; // AND
12083 when �0001� result = R[n] EOR operand2; // EOR
12084 when �0010� (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
12085 when �0011� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
12086 when �0100� (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
12087 when �0101� (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12088 when �0110� (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12089 when �0111� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12090 when �1100� result = R[n] OR operand2; // ORR
12091 when �1101� result = operand2; // MOV
12092 when �1110� result = R[n] AND NOT(operand2); // BIC
12093 when �1111� result = NOT(operand2); // MVN
12094 CPSRWriteByInstr(SPSR[], �1111�, TRUE);
12095 BranchWritePC(result);
12096 #endif
12097
12098 bool success = false;
12099
12100 if (ConditionPassed (opcode))
12101 {
12102 uint32_t n;
12103 uint32_t m;
12104 uint32_t imm32;
12105 bool register_form;
12106 ARM_ShifterType shift_t;
12107 uint32_t shift_n;
12108 uint32_t code;
12109
12110 switch (encoding)
12111 {
12112 case eEncodingT1:
12113 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
12114 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = �0010�; // = SUB
12115 n = 14;
12116 imm32 = Bits32 (opcode, 7, 0);
12117 register_form = false;
12118 code = 2;
12119
12120 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12121 if (InITBlock() && !LastInITBlock())
12122 return false;
12123
12124 break;
12125
12126 case eEncodingA1:
12127 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12128 n = Bits32 (opcode, 19, 16);
12129 imm32 = ARMExpandImm (opcode);
12130 register_form = false;
12131 code = Bits32 (opcode, 24, 21);
12132
12133 break;
12134
12135 case eEncodingA2:
12136 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12137 n = Bits32 (opcode, 19, 16);
12138 m = Bits32 (opcode, 3, 0);
12139 register_form = true;
12140
12141 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12142 shift_n = DecodeImmShiftARM (opcode, shift_t);
12143
12144 break;
12145
12146 default:
12147 return false;
12148 }
12149
12150 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12151 uint32_t operand2;
12152 if (register_form)
12153 {
12154 uint32_t Rm = ReadCoreReg (m, &success);
12155 if (!success)
12156 return false;
12157
12158 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12159 if (!success)
12160 return false;
12161 }
12162 else
12163 {
12164 operand2 = imm32;
12165 }
12166
12167 uint32_t Rn = ReadCoreReg (n, &success);
12168 if (!success)
12169 return false;
12170
12171 AddWithCarryResult result;
12172
12173 // case opcode of
12174 switch (code)
12175 {
12176 case 0: // when �0000�
12177 // result = R[n] AND operand2; // AND
12178 result.result = Rn & operand2;
12179 break;
12180
12181 case 1: // when �0001�
12182 // result = R[n] EOR operand2; // EOR
12183 result.result = Rn ^ operand2;
12184 break;
12185
12186 case 2: // when �0010�
12187 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
12188 result = AddWithCarry (Rn, ~(operand2), 1);
12189 break;
12190
12191 case 3: // when �0011�
12192 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
12193 result = AddWithCarry (~(Rn), operand2, 1);
12194 break;
12195
12196 case 4: // when �0100�
12197 // (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
12198 result = AddWithCarry (Rn, operand2, 0);
12199 break;
12200
12201 case 5: // when �0101�
12202 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12203 result = AddWithCarry (Rn, operand2, APSR_C);
12204 break;
12205
12206 case 6: // when �0110�
12207 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12208 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12209 break;
12210
12211 case 7: // when �0111�
12212 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12213 result = AddWithCarry (~(Rn), operand2, APSR_C);
12214 break;
12215
12216 case 10: // when �1100�
12217 // result = R[n] OR operand2; // ORR
12218 result.result = Rn | operand2;
12219 break;
12220
12221 case 11: // when �1101�
12222 // result = operand2; // MOV
12223 result.result = operand2;
12224 break;
12225
12226 case 12: // when �1110�
12227 // result = R[n] AND NOT(operand2); // BIC
12228 result.result = Rn & ~(operand2);
12229 break;
12230
12231 case 15: // when �1111�
12232 // result = NOT(operand2); // MVN
12233 result.result = ~(operand2);
12234 break;
12235
12236 default:
12237 return false;
12238 }
12239 // CPSRWriteByInstr(SPSR[], �1111�, TRUE);
12240
12241 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12242 // the best.
12243 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12244 if (!success)
12245 return false;
12246
12247 CPSRWriteByInstr (spsr, 15, true);
12248
12249 // BranchWritePC(result);
12250 EmulateInstruction::Context context;
12251 context.type = eContextAdjustPC;
12252 context.SetImmediate (result.result);
12253
12254 BranchWritePC (context, result.result);
12255 }
12256 return true;
12257 }
12258
12259 EmulateInstructionARM::ARMOpcode*
GetARMOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)12260 EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
12261 {
12262 static ARMOpcode
12263 g_arm_opcodes[] =
12264 {
12265 //----------------------------------------------------------------------
12266 // Prologue instructions
12267 //----------------------------------------------------------------------
12268
12269 // push register(s)
12270 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12271 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
12272
12273 // set r7 to point to a stack offset
12274 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12275 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12276 // copy the stack pointer to ip
12277 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12278 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12279 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12280
12281 // adjust the stack pointer
12282 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12283 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
12284
12285 // push one register
12286 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12287 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
12288
12289 // vector push consecutive extension register(s)
12290 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12291 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12292
12293 //----------------------------------------------------------------------
12294 // Epilogue instructions
12295 //----------------------------------------------------------------------
12296
12297 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12298 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12299 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12300 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12301
12302 //----------------------------------------------------------------------
12303 // Supervisor Call (previously Software Interrupt)
12304 //----------------------------------------------------------------------
12305 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12306
12307 //----------------------------------------------------------------------
12308 // Branch instructions
12309 //----------------------------------------------------------------------
12310 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
12311 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
12312 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12313 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12314 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12315 // for example, "bx lr"
12316 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12317 // bxj
12318 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12319
12320 //----------------------------------------------------------------------
12321 // Data-processing instructions
12322 //----------------------------------------------------------------------
12323 // adc (immediate)
12324 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12325 // adc (register)
12326 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12327 // add (immediate)
12328 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
12329 // add (register)
12330 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12331 // add (register-shifted register)
12332 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12333 // adr
12334 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12335 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12336 // and (immediate)
12337 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12338 // and (register)
12339 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12340 // bic (immediate)
12341 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12342 // bic (register)
12343 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12344 // eor (immediate)
12345 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12346 // eor (register)
12347 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12348 // orr (immediate)
12349 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12350 // orr (register)
12351 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12352 // rsb (immediate)
12353 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12354 // rsb (register)
12355 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12356 // rsc (immediate)
12357 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12358 // rsc (register)
12359 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12360 // sbc (immediate)
12361 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12362 // sbc (register)
12363 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12364 // sub (immediate, ARM)
12365 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
12366 // sub (sp minus immediate)
12367 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12368 // sub (register)
12369 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12370 // teq (immediate)
12371 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12372 // teq (register)
12373 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12374 // tst (immediate)
12375 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12376 // tst (register)
12377 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12378
12379 // mov (immediate)
12380 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12381 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
12382 // mov (register)
12383 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12384 // mvn (immediate)
12385 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12386 // mvn (register)
12387 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12388 // cmn (immediate)
12389 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
12390 // cmn (register)
12391 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
12392 // cmp (immediate)
12393 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
12394 // cmp (register)
12395 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
12396 // asr (immediate)
12397 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
12398 // asr (register)
12399 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
12400 // lsl (immediate)
12401 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
12402 // lsl (register)
12403 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
12404 // lsr (immediate)
12405 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
12406 // lsr (register)
12407 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
12408 // rrx is a special case encoding of ror (immediate)
12409 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
12410 // ror (immediate)
12411 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
12412 // ror (register)
12413 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
12414 // mul
12415 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
12416
12417 // subs pc, lr and related instructions
12418 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12419 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
12420
12421 //----------------------------------------------------------------------
12422 // Load instructions
12423 //----------------------------------------------------------------------
12424 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12425 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12426 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12427 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12428 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12429 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12430 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12431 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12432 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12433 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12434 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12435 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12436 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12437 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12438 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12439 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12440 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12441 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12442 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12443 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12444 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12445 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12446 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12447 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12448 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12449
12450 //----------------------------------------------------------------------
12451 // Store instructions
12452 //----------------------------------------------------------------------
12453 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12454 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12455 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12456 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12457 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12458 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12459 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12460 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12461 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12462 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
12463 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
12464 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12465 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12466 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12467 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12468 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12469 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12470
12471 //----------------------------------------------------------------------
12472 // Other instructions
12473 //----------------------------------------------------------------------
12474 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12475 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12476 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12477 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12478 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
12479
12480 };
12481 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12482
12483 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12484 {
12485 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12486 (g_arm_opcodes[i].variants & arm_isa) != 0)
12487 return &g_arm_opcodes[i];
12488 }
12489 return NULL;
12490 }
12491
12492
12493 EmulateInstructionARM::ARMOpcode*
GetThumbOpcodeForInstruction(const uint32_t opcode,uint32_t arm_isa)12494 EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
12495 {
12496
12497 static ARMOpcode
12498 g_thumb_opcodes[] =
12499 {
12500 //----------------------------------------------------------------------
12501 // Prologue instructions
12502 //----------------------------------------------------------------------
12503
12504 // push register(s)
12505 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12506 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12507 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
12508
12509 // set r7 to point to a stack offset
12510 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
12511 // copy the stack pointer to r7
12512 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
12513 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
12514 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
12515
12516 // PC-relative load into register (see also EmulateADDSPRm)
12517 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
12518
12519 // adjust the stack pointer
12520 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12521 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12522 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12523 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12524 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
12525
12526 // vector push consecutive extension register(s)
12527 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12528 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12529
12530 //----------------------------------------------------------------------
12531 // Epilogue instructions
12532 //----------------------------------------------------------------------
12533
12534 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12535 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12536 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12537 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12538 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12539 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12540 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12541
12542 //----------------------------------------------------------------------
12543 // Supervisor Call (previously Software Interrupt)
12544 //----------------------------------------------------------------------
12545 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
12546
12547 //----------------------------------------------------------------------
12548 // If Then makes up to four following instructions conditional.
12549 //----------------------------------------------------------------------
12550 // The next 5 opcode _must_ come before the if then instruction
12551 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12552 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12553 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12554 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12555 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12556 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
12557
12558 //----------------------------------------------------------------------
12559 // Branch instructions
12560 //----------------------------------------------------------------------
12561 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
12562 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12563 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12564 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12565 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
12566 // J1 == J2 == 1
12567 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12568 // J1 == J2 == 1
12569 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12570 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12571 // for example, "bx lr"
12572 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12573 // bxj
12574 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12575 // compare and branch
12576 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
12577 // table branch byte
12578 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
12579 // table branch halfword
12580 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
12581
12582 //----------------------------------------------------------------------
12583 // Data-processing instructions
12584 //----------------------------------------------------------------------
12585 // adc (immediate)
12586 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
12587 // adc (register)
12588 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12589 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12590 // add (register)
12591 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
12592 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
12593 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
12594 // adr
12595 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12596 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12597 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12598 // and (immediate)
12599 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
12600 // and (register)
12601 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12602 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12603 // bic (immediate)
12604 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
12605 // bic (register)
12606 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12607 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12608 // eor (immediate)
12609 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
12610 // eor (register)
12611 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12612 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12613 // orr (immediate)
12614 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
12615 // orr (register)
12616 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12617 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12618 // rsb (immediate)
12619 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12620 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
12621 // rsb (register)
12622 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12623 // sbc (immediate)
12624 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12625 // sbc (register)
12626 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12627 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
12628 // add (immediate, Thumb)
12629 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12630 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12631 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12632 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
12633 // sub (immediate, Thumb)
12634 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12635 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12636 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12637 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
12638 // sub (sp minus immediate)
12639 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12640 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
12641 // sub (register)
12642 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12643 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
12644 // teq (immediate)
12645 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
12646 // teq (register)
12647 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12648 // tst (immediate)
12649 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
12650 // tst (register)
12651 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12652 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
12653
12654
12655 // move from high register to high register
12656 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
12657 // move from low register to low register
12658 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
12659 // mov{s}<c>.w <Rd>, <Rm>
12660 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
12661 // move immediate
12662 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12663 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12664 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
12665 // mvn (immediate)
12666 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
12667 // mvn (register)
12668 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12669 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
12670 // cmn (immediate)
12671 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
12672 // cmn (register)
12673 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12674 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
12675 // cmp (immediate)
12676 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12677 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
12678 // cmp (register) (Rn and Rm both from r0-r7)
12679 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
12680 // cmp (register) (Rn and Rm not both from r0-r7)
12681 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
12682 // asr (immediate)
12683 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12684 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
12685 // asr (register)
12686 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12687 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
12688 // lsl (immediate)
12689 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12690 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
12691 // lsl (register)
12692 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12693 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
12694 // lsr (immediate)
12695 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12696 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
12697 // lsr (register)
12698 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12699 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
12700 // rrx is a special case encoding of ror (immediate)
12701 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
12702 // ror (immediate)
12703 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
12704 // ror (register)
12705 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12706 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
12707 // mul
12708 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
12709 // mul
12710 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
12711
12712 // subs pc, lr and related instructions
12713 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
12714
12715 //----------------------------------------------------------------------
12716 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12717 // otherwise the wrong instructions will be selected.
12718 //----------------------------------------------------------------------
12719
12720 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12721 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12722
12723 //----------------------------------------------------------------------
12724 // Load instructions
12725 //----------------------------------------------------------------------
12726 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12727 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12728 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12729 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12730 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12731 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12732 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
12733 // Thumb2 PC-relative load into register
12734 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12735 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12736 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12737 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12738 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12739 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
12740 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12741 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12742 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12743 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12744 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12745 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12746 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12747 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12748 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12749 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12750 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12751 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12752 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12753 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12754 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12755 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12756 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12757 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12758 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12759 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
12760 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12761 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12762 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12763 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
12764 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12765 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12766 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12767
12768 //----------------------------------------------------------------------
12769 // Store instructions
12770 //----------------------------------------------------------------------
12771 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12772 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12773 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12774 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12775 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12776 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12777 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12778 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12779 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12780 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12781 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12782 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12783 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12784 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12785 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12786 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
12787 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12788 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12789 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12790 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12791 { 0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12792 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12793
12794 //----------------------------------------------------------------------
12795 // Other instructions
12796 //----------------------------------------------------------------------
12797 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12798 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12799 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12800 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12801 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12802 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12803 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12804 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12805 };
12806
12807 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12808 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12809 {
12810 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12811 (g_thumb_opcodes[i].variants & arm_isa) != 0)
12812 return &g_thumb_opcodes[i];
12813 }
12814 return NULL;
12815 }
12816
12817 bool
SetArchitecture(const ArchSpec & arch)12818 EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
12819 {
12820 m_arch = arch;
12821 m_arm_isa = 0;
12822 const char *arch_cstr = arch.GetArchitectureName ();
12823 if (arch_cstr)
12824 {
12825 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12826 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12827 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12828 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12829 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12830 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12831 else if (0 == ::strcasecmp(arch_cstr, "armv7s")) m_arm_isa = ARMv7S;
12832 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12833 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
12834 else if (0 == ::strncasecmp(arch_cstr,"armv4", 5)) m_arm_isa = ARMv4;
12835 else if (0 == ::strncasecmp(arch_cstr,"armv6", 5)) m_arm_isa = ARMv6;
12836 else if (0 == ::strncasecmp(arch_cstr,"armv7", 5)) m_arm_isa = ARMv7;
12837 else if (0 == ::strncasecmp(arch_cstr,"armv8", 5)) m_arm_isa = ARMv8;
12838 }
12839 return m_arm_isa != 0;
12840 }
12841
12842 bool
SetInstruction(const Opcode & insn_opcode,const Address & inst_addr,Target * target)12843 EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
12844 {
12845 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12846 {
12847 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12848 m_opcode_mode = eModeThumb;
12849 else
12850 {
12851 AddressClass addr_class = inst_addr.GetAddressClass();
12852
12853 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12854 m_opcode_mode = eModeARM;
12855 else if (addr_class == eAddressClassCodeAlternateISA)
12856 m_opcode_mode = eModeThumb;
12857 else
12858 return false;
12859 }
12860 if (m_opcode_mode == eModeThumb)
12861 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12862 else
12863 m_opcode_cpsr = CPSR_MODE_USR;
12864 return true;
12865 }
12866 return false;
12867 }
12868
12869 bool
ReadInstruction()12870 EmulateInstructionARM::ReadInstruction ()
12871 {
12872 bool success = false;
12873 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
12874 if (success)
12875 {
12876 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12877 if (success)
12878 {
12879 Context read_inst_context;
12880 read_inst_context.type = eContextReadOpcode;
12881 read_inst_context.SetNoArgs ();
12882
12883 if (m_opcode_cpsr & MASK_CPSR_T)
12884 {
12885 m_opcode_mode = eModeThumb;
12886 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
12887
12888 if (success)
12889 {
12890 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
12891 {
12892 m_opcode.SetOpcode16 (thumb_opcode);
12893 }
12894 else
12895 {
12896 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
12897 }
12898 }
12899 }
12900 else
12901 {
12902 m_opcode_mode = eModeARM;
12903 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
12904 }
12905 }
12906 }
12907 if (!success)
12908 {
12909 m_opcode_mode = eModeInvalid;
12910 m_addr = LLDB_INVALID_ADDRESS;
12911 }
12912 return success;
12913 }
12914
12915 uint32_t
ArchVersion()12916 EmulateInstructionARM::ArchVersion ()
12917 {
12918 return m_arm_isa;
12919 }
12920
12921 bool
ConditionPassed(const uint32_t opcode,bool * is_conditional)12922 EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
12923 {
12924 // If we are ignoring conditions, then always return true.
12925 // this allows us to iterate over disassembly code and still
12926 // emulate an instruction even if we don't have all the right
12927 // bits set in the CPSR register...
12928 if (m_ignore_conditions)
12929 return true;
12930
12931 if (is_conditional)
12932 *is_conditional = true;
12933
12934 const uint32_t cond = CurrentCond (opcode);
12935
12936 if (cond == UINT32_MAX)
12937 return false;
12938
12939 bool result = false;
12940 switch (UnsignedBits(cond, 3, 1))
12941 {
12942 case 0:
12943 if (m_opcode_cpsr == 0)
12944 result = true;
12945 else
12946 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12947 break;
12948 case 1:
12949 if (m_opcode_cpsr == 0)
12950 result = true;
12951 else
12952 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12953 break;
12954 case 2:
12955 if (m_opcode_cpsr == 0)
12956 result = true;
12957 else
12958 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12959 break;
12960 case 3:
12961 if (m_opcode_cpsr == 0)
12962 result = true;
12963 else
12964 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12965 break;
12966 case 4:
12967 if (m_opcode_cpsr == 0)
12968 result = true;
12969 else
12970 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12971 break;
12972 case 5:
12973 if (m_opcode_cpsr == 0)
12974 result = true;
12975 else
12976 {
12977 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12978 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12979 result = n == v;
12980 }
12981 break;
12982 case 6:
12983 if (m_opcode_cpsr == 0)
12984 result = true;
12985 else
12986 {
12987 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12988 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12989 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12990 }
12991 break;
12992 case 7:
12993 // Always execute (cond == 0b1110, or the special 0b1111 which gives
12994 // opcodes different meanings, but always means execution happpens.
12995 if (is_conditional)
12996 *is_conditional = false;
12997 result = true;
12998 break;
12999 }
13000
13001 if (cond & 1)
13002 result = !result;
13003 return result;
13004 }
13005
13006 uint32_t
CurrentCond(const uint32_t opcode)13007 EmulateInstructionARM::CurrentCond (const uint32_t opcode)
13008 {
13009 switch (m_opcode_mode)
13010 {
13011 case eModeInvalid:
13012 break;
13013
13014 case eModeARM:
13015 return UnsignedBits(opcode, 31, 28);
13016
13017 case eModeThumb:
13018 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13019 // 'cond' field of the encoding.
13020 {
13021 const uint32_t byte_size = m_opcode.GetByteSize();
13022 if (byte_size == 2)
13023 {
13024 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
13025 return Bits32(opcode, 11, 7);
13026 }
13027 else if (byte_size == 4)
13028 {
13029 if (Bits32(opcode, 31, 27) == 0x1e &&
13030 Bits32(opcode, 15, 14) == 0x02 &&
13031 Bits32(opcode, 12, 12) == 0x00 &&
13032 Bits32(opcode, 25, 22) <= 0x0d)
13033 {
13034 return Bits32(opcode, 25, 22);
13035 }
13036 }
13037 else
13038 // We have an invalid thumb instruction, let's bail out.
13039 break;
13040
13041 return m_it_session.GetCond();
13042 }
13043 }
13044 return UINT32_MAX; // Return invalid value
13045 }
13046
13047 bool
InITBlock()13048 EmulateInstructionARM::InITBlock()
13049 {
13050 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13051 }
13052
13053 bool
LastInITBlock()13054 EmulateInstructionARM::LastInITBlock()
13055 {
13056 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13057 }
13058
13059 bool
BadMode(uint32_t mode)13060 EmulateInstructionARM::BadMode (uint32_t mode)
13061 {
13062
13063 switch (mode)
13064 {
13065 case 16: return false; // '10000'
13066 case 17: return false; // '10001'
13067 case 18: return false; // '10010'
13068 case 19: return false; // '10011'
13069 case 22: return false; // '10110'
13070 case 23: return false; // '10111'
13071 case 27: return false; // '11011'
13072 case 31: return false; // '11111'
13073 default: return true;
13074 }
13075 return true;
13076 }
13077
13078 bool
CurrentModeIsPrivileged()13079 EmulateInstructionARM::CurrentModeIsPrivileged ()
13080 {
13081 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
13082
13083 if (BadMode (mode))
13084 return false;
13085
13086 if (mode == 16)
13087 return false;
13088
13089 return true;
13090 }
13091
13092 void
CPSRWriteByInstr(uint32_t value,uint32_t bytemask,bool affect_execstate)13093 EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13094 {
13095 bool privileged = CurrentModeIsPrivileged();
13096
13097 uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20;
13098
13099 if (BitIsSet (bytemask, 3))
13100 {
13101 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13102 if (affect_execstate)
13103 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13104 }
13105
13106 if (BitIsSet (bytemask, 2))
13107 {
13108 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13109 }
13110
13111 if (BitIsSet (bytemask, 1))
13112 {
13113 if (affect_execstate)
13114 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13115 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13116 if (privileged)
13117 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13118 }
13119
13120 if (BitIsSet (bytemask, 0))
13121 {
13122 if (privileged)
13123 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13124 if (affect_execstate)
13125 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13126 if (privileged)
13127 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13128 }
13129
13130 m_opcode_cpsr = tmp_cpsr;
13131 }
13132
13133
13134 bool
BranchWritePC(const Context & context,uint32_t addr)13135 EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13136 {
13137 addr_t target;
13138
13139 // Check the current instruction set.
13140 if (CurrentInstrSet() == eModeARM)
13141 target = addr & 0xfffffffc;
13142 else
13143 target = addr & 0xfffffffe;
13144
13145 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
13146 return false;
13147
13148 return true;
13149 }
13150
13151 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13152 bool
BXWritePC(Context & context,uint32_t addr)13153 EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
13154 {
13155 addr_t target;
13156 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13157 // we want to record it and issue a WriteRegister callback so the clients
13158 // can track the mode changes accordingly.
13159 bool cpsr_changed = false;
13160
13161 if (BitIsSet(addr, 0))
13162 {
13163 if (CurrentInstrSet() != eModeThumb)
13164 {
13165 SelectInstrSet(eModeThumb);
13166 cpsr_changed = true;
13167 }
13168 target = addr & 0xfffffffe;
13169 context.SetISA (eModeThumb);
13170 }
13171 else if (BitIsClear(addr, 1))
13172 {
13173 if (CurrentInstrSet() != eModeARM)
13174 {
13175 SelectInstrSet(eModeARM);
13176 cpsr_changed = true;
13177 }
13178 target = addr & 0xfffffffc;
13179 context.SetISA (eModeARM);
13180 }
13181 else
13182 return false; // address<1:0> == '10' => UNPREDICTABLE
13183
13184 if (cpsr_changed)
13185 {
13186 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13187 return false;
13188 }
13189 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
13190 return false;
13191
13192 return true;
13193 }
13194
13195 // Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13196 bool
LoadWritePC(Context & context,uint32_t addr)13197 EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
13198 {
13199 if (ArchVersion() >= ARMv5T)
13200 return BXWritePC(context, addr);
13201 else
13202 return BranchWritePC((const Context)context, addr);
13203 }
13204
13205 // Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13206 bool
ALUWritePC(Context & context,uint32_t addr)13207 EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
13208 {
13209 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
13210 return BXWritePC(context, addr);
13211 else
13212 return BranchWritePC((const Context)context, addr);
13213 }
13214
13215 EmulateInstructionARM::Mode
CurrentInstrSet()13216 EmulateInstructionARM::CurrentInstrSet ()
13217 {
13218 return m_opcode_mode;
13219 }
13220
13221 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
13222 // ReadInstruction() is performed. This function has a side effect of updating
13223 // the m_new_inst_cpsr member variable if necessary.
13224 bool
SelectInstrSet(Mode arm_or_thumb)13225 EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13226 {
13227 m_new_inst_cpsr = m_opcode_cpsr;
13228 switch (arm_or_thumb)
13229 {
13230 default:
13231 return false;
13232 case eModeARM:
13233 // Clear the T bit.
13234 m_new_inst_cpsr &= ~MASK_CPSR_T;
13235 break;
13236 case eModeThumb:
13237 // Set the T bit.
13238 m_new_inst_cpsr |= MASK_CPSR_T;
13239 break;
13240 }
13241 return true;
13242 }
13243
13244 // This function returns TRUE if the processor currently provides support for
13245 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13246 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13247 bool
UnalignedSupport()13248 EmulateInstructionARM::UnalignedSupport()
13249 {
13250 return (ArchVersion() >= ARMv7);
13251 }
13252
13253 // The main addition and subtraction instructions can produce status information
13254 // about both unsigned carry and signed overflow conditions. This status
13255 // information can be used to synthesize multi-word additions and subtractions.
13256 EmulateInstructionARM::AddWithCarryResult
AddWithCarry(uint32_t x,uint32_t y,uint8_t carry_in)13257 EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13258 {
13259 uint32_t result;
13260 uint8_t carry_out;
13261 uint8_t overflow;
13262
13263 uint64_t unsigned_sum = x + y + carry_in;
13264 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13265
13266 result = UnsignedBits(unsigned_sum, 31, 0);
13267 // carry_out = (result == unsigned_sum ? 0 : 1);
13268 overflow = ((int32_t)result == signed_sum ? 0 : 1);
13269
13270 if (carry_in)
13271 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
13272 else
13273 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
13274
13275 AddWithCarryResult res = { result, carry_out, overflow };
13276 return res;
13277 }
13278
13279 uint32_t
ReadCoreReg(uint32_t num,bool * success)13280 EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
13281 {
13282 uint32_t reg_kind, reg_num;
13283 switch (num)
13284 {
13285 case SP_REG:
13286 reg_kind = eRegisterKindGeneric;
13287 reg_num = LLDB_REGNUM_GENERIC_SP;
13288 break;
13289 case LR_REG:
13290 reg_kind = eRegisterKindGeneric;
13291 reg_num = LLDB_REGNUM_GENERIC_RA;
13292 break;
13293 case PC_REG:
13294 reg_kind = eRegisterKindGeneric;
13295 reg_num = LLDB_REGNUM_GENERIC_PC;
13296 break;
13297 default:
13298 if (num < SP_REG)
13299 {
13300 reg_kind = eRegisterKindDWARF;
13301 reg_num = dwarf_r0 + num;
13302 }
13303 else
13304 {
13305 //assert(0 && "Invalid register number");
13306 *success = false;
13307 return UINT32_MAX;
13308 }
13309 break;
13310 }
13311
13312 // Read our register.
13313 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13314
13315 // When executing an ARM instruction , PC reads as the address of the current
13316 // instruction plus 8.
13317 // When executing a Thumb instruction , PC reads as the address of the current
13318 // instruction plus 4.
13319 if (num == 15)
13320 {
13321 if (CurrentInstrSet() == eModeARM)
13322 val += 8;
13323 else
13324 val += 4;
13325 }
13326
13327 return val;
13328 }
13329
13330 // Write the result to the ARM core register Rd, and optionally update the
13331 // condition flags based on the result.
13332 //
13333 // This helper method tries to encapsulate the following pseudocode from the
13334 // ARM Architecture Reference Manual:
13335 //
13336 // if d == 15 then // Can only occur for encoding A1
13337 // ALUWritePC(result); // setflags is always FALSE here
13338 // else
13339 // R[d] = result;
13340 // if setflags then
13341 // APSR.N = result<31>;
13342 // APSR.Z = IsZeroBit(result);
13343 // APSR.C = carry;
13344 // // APSR.V unchanged
13345 //
13346 // In the above case, the API client does not pass in the overflow arg, which
13347 // defaults to ~0u.
13348 bool
WriteCoreRegOptionalFlags(Context & context,const uint32_t result,const uint32_t Rd,bool setflags,const uint32_t carry,const uint32_t overflow)13349 EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13350 const uint32_t result,
13351 const uint32_t Rd,
13352 bool setflags,
13353 const uint32_t carry,
13354 const uint32_t overflow)
13355 {
13356 if (Rd == 15)
13357 {
13358 if (!ALUWritePC (context, result))
13359 return false;
13360 }
13361 else
13362 {
13363 uint32_t reg_kind, reg_num;
13364 switch (Rd)
13365 {
13366 case SP_REG:
13367 reg_kind = eRegisterKindGeneric;
13368 reg_num = LLDB_REGNUM_GENERIC_SP;
13369 break;
13370 case LR_REG:
13371 reg_kind = eRegisterKindGeneric;
13372 reg_num = LLDB_REGNUM_GENERIC_RA;
13373 break;
13374 default:
13375 reg_kind = eRegisterKindDWARF;
13376 reg_num = dwarf_r0 + Rd;
13377 }
13378 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
13379 return false;
13380 if (setflags)
13381 return WriteFlags (context, result, carry, overflow);
13382 }
13383 return true;
13384 }
13385
13386 // This helper method tries to encapsulate the following pseudocode from the
13387 // ARM Architecture Reference Manual:
13388 //
13389 // APSR.N = result<31>;
13390 // APSR.Z = IsZeroBit(result);
13391 // APSR.C = carry;
13392 // APSR.V = overflow
13393 //
13394 // Default arguments can be specified for carry and overflow parameters, which means
13395 // not to update the respective flags.
13396 bool
WriteFlags(Context & context,const uint32_t result,const uint32_t carry,const uint32_t overflow)13397 EmulateInstructionARM::WriteFlags (Context &context,
13398 const uint32_t result,
13399 const uint32_t carry,
13400 const uint32_t overflow)
13401 {
13402 m_new_inst_cpsr = m_opcode_cpsr;
13403 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13404 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
13405 if (carry != ~0u)
13406 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
13407 if (overflow != ~0u)
13408 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
13409 if (m_new_inst_cpsr != m_opcode_cpsr)
13410 {
13411 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13412 return false;
13413 }
13414 return true;
13415 }
13416
13417 bool
EvaluateInstruction(uint32_t evaluate_options)13418 EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
13419 {
13420 // Advance the ITSTATE bits to their values for the next instruction.
13421 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
13422 m_it_session.ITAdvance();
13423
13424 ARMOpcode *opcode_data = NULL;
13425
13426 if (m_opcode_mode == eModeThumb)
13427 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13428 else if (m_opcode_mode == eModeARM)
13429 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13430
13431 if (opcode_data == NULL)
13432 return false;
13433
13434 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13435 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
13436
13437 bool success = false;
13438 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
13439 {
13440 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
13441 dwarf_cpsr,
13442 0,
13443 &success);
13444 }
13445
13446 // Only return false if we are unable to read the CPSR if we care about conditions
13447 if (success == false && m_ignore_conditions == false)
13448 return false;
13449
13450 uint32_t orig_pc_value = 0;
13451 if (auto_advance_pc)
13452 {
13453 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13454 if (!success)
13455 return false;
13456 }
13457
13458 // Call the Emulate... function.
13459 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13460 if (!success)
13461 return false;
13462
13463 if (auto_advance_pc)
13464 {
13465 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13466 if (!success)
13467 return false;
13468
13469 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13470 {
13471 if (opcode_data->size == eSize32)
13472 after_pc_value += 4;
13473 else if (opcode_data->size == eSize16)
13474 after_pc_value += 2;
13475
13476 EmulateInstruction::Context context;
13477 context.type = eContextAdvancePC;
13478 context.SetNoArgs();
13479 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13480 return false;
13481
13482 }
13483 }
13484 return true;
13485 }
13486
13487 bool
TestEmulation(Stream * out_stream,ArchSpec & arch,OptionValueDictionary * test_data)13488 EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
13489 {
13490 if (!test_data)
13491 {
13492 out_stream->Printf ("TestEmulation: Missing test data.\n");
13493 return false;
13494 }
13495
13496 static ConstString opcode_key ("opcode");
13497 static ConstString before_key ("before_state");
13498 static ConstString after_key ("after_state");
13499
13500 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
13501
13502 uint32_t test_opcode;
13503 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
13504 {
13505 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
13506 return false;
13507 }
13508 test_opcode = value_sp->GetUInt64Value ();
13509
13510 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13511 {
13512 m_opcode_mode = eModeARM;
13513 m_opcode.SetOpcode32 (test_opcode);
13514 }
13515 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13516 {
13517 m_opcode_mode = eModeThumb;
13518 if (test_opcode < 0x10000)
13519 m_opcode.SetOpcode16 (test_opcode);
13520 else
13521 m_opcode.SetOpcode32 (test_opcode);
13522
13523 }
13524 else
13525 {
13526 out_stream->Printf ("TestEmulation: Invalid arch.\n");
13527 return false;
13528 }
13529
13530 EmulationStateARM before_state;
13531 EmulationStateARM after_state;
13532
13533 value_sp = test_data->GetValueForKey (before_key);
13534 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
13535 {
13536 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
13537 return false;
13538 }
13539
13540 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
13541 if (!before_state.LoadStateFromDictionary (state_dictionary))
13542 {
13543 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
13544 return false;
13545 }
13546
13547 value_sp = test_data->GetValueForKey (after_key);
13548 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
13549 {
13550 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
13551 return false;
13552 }
13553
13554 state_dictionary = value_sp->GetAsDictionary ();
13555 if (!after_state.LoadStateFromDictionary (state_dictionary))
13556 {
13557 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13558 return false;
13559 }
13560
13561 SetBaton ((void *) &before_state);
13562 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13563 &EmulationStateARM::WritePseudoMemory,
13564 &EmulationStateARM::ReadPseudoRegister,
13565 &EmulationStateARM::WritePseudoRegister);
13566
13567 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
13568 if (!success)
13569 {
13570 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
13571 return false;
13572 }
13573
13574 success = before_state.CompareState (after_state);
13575 if (!success)
13576 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13577
13578 return success;
13579 }
13580 //
13581 //
13582 //const char *
13583 //EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13584 //{
13585 // if (reg_kind == eRegisterKindGeneric)
13586 // {
13587 // switch (reg_num)
13588 // {
13589 // case LLDB_REGNUM_GENERIC_PC: return "pc";
13590 // case LLDB_REGNUM_GENERIC_SP: return "sp";
13591 // case LLDB_REGNUM_GENERIC_FP: return "fp";
13592 // case LLDB_REGNUM_GENERIC_RA: return "lr";
13593 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13594 // default: return NULL;
13595 // }
13596 // }
13597 // else if (reg_kind == eRegisterKindDWARF)
13598 // {
13599 // return GetARMDWARFRegisterName (reg_num);
13600 // }
13601 // return NULL;
13602 //}
13603 //
13604 bool
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)13605 EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
13606 {
13607 unwind_plan.Clear();
13608 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13609
13610 UnwindPlan::RowSP row(new UnwindPlan::Row);
13611
13612 // Our previous Call Frame Address is the stack pointer
13613 row->SetCFARegister (dwarf_sp);
13614
13615 // Our previous PC is in the LR
13616 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
13617 unwind_plan.AppendRow (row);
13618
13619 // All other registers are the same.
13620
13621 unwind_plan.SetSourceName ("EmulateInstructionARM");
13622 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
13623 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
13624 return true;
13625 }
13626